Libraries used in the Project and uploading data

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.3     ✓ purrr   0.3.4
✓ tibble  3.0.3     ✓ dplyr   1.0.2
✓ tidyr   1.1.2     ✓ stringr 1.4.0
✓ readr   1.4.0     ✓ forcats 0.5.0
── Conflicts ───────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(dplyr)
library(stringr)
library(svMisc)

Attaching package: ‘svMisc’

The following object is masked from ‘package:utils’:

    ?
library(ggplot2)
library(gtable)
library("ggpubr")
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
log_data <- read_csv("~/Desktop/PAE/github/data/logData.csv")

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  callerId = col_double(),
  langId = col_double(),
  callTime = col_datetime(format = ""),
  lastCallTime = col_character(),
  noCallsMade = col_double(),
  noContentListened = col_double(),
  callId = col_character(),
  eventTime = col_datetime(format = ""),
  logInfo = col_character(),
  logInfoId = col_double(),
  inSurvey = col_logical()
)
log_data <- read_csv("~/Desktop/PAE/github/data/benData_weakCallers.csv")

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  callerId = col_double(),
  phoneNum = col_character(),
  langId = col_double(),
  callTime = col_datetime(format = ""),
  lastCallTime = col_datetime(format = ""),
  noCallsMade = col_double(),
  noContentListened = col_double(),
  callId = col_logical(),
  eventTime = col_datetime(format = ""),
  logInfo = col_character(),
  logInfoId = col_double()
)
log_data_saver <- log_data

log_data <- unique(log_data)

log_data$logInfo <- str_replace(log_data$logInfo, "  ", " ")

#MAKE IT ALL UPPER!!!

log_data$logInfo <- toupper(log_data$logInfo)

### GETTING THE DATE MONTH AND YEAR IF I WANT!!!
extractdate <- function(date) {
    day <- format(date, format="%d")
    month <- format(date, format="%m")
    year <- format(date, format="%Y")

    cbind(day, month, year)
}

#making first calls
first_call<-extractdate(log_data$callTime)


#making last call
last_day <-substr(log_data$lastCallTime, 9, 10)
last_month <- substr(log_data$lastCallTime, 6, 7)
last_year <-substr(log_data$lastCallTime, 1, 4)

log_data<-cbind(log_data, first_call,last_day,last_month,last_year)

#Converting columns to numeric
log_data$day <-as.numeric(log_data$day)
log_data$last_day <- as.numeric(log_data$last_day)
log_data$month <-as.numeric(log_data$month)
log_data$last_month <- as.numeric(log_data$last_month)
log_data$year <- as.numeric(log_data$year)
log_data$last_year <- as.numeric(log_data$last_year )


log_data$year <- log_data$year +log_data$month/12
log_data$last_year <- log_data$last_year + log_data$last_month/12

log_data$caller_lifetime <- log_data$last_year - log_data$year

Cmd+Option+I.

Cmd+Shift+K

PRELIMINARY DISTRIBUTIONS

In this section, we display some of the basic distributions of the data including languages, total lifeetime of a given caller, colls made, content accessed, and the ratio of content listened to calls made.

Based on the graphs below, we are nervous that some of the data is not random given the incredibly high ratio for content listened to calls made, but given that the data is distributed fairly evenly across thee different graphs, we are unsure

lang_spoken <- log_data %>%
  group_by(callerId, langId) %>%
  count()

#Distribution of languages spoken
ggplot(data=lang_spoken, aes(x=langId)) +
  geom_bar(fill='red')+
  geom_text(stat='count', aes(label=..count../16445), vjust=-1)+
  ylim(0,600)+
  labs(
    title = 'Distribution of Languages by Caller
    1 = Amharic, 2=Oromiffa, 3=Tigrigna, 4=Wolayitta, and 5=Sidamigna',
    x = 'Language',
    y= 'count'
  )



#Distribution of time difference bewtween first and last call

lifetime<- log_data %>%
  group_by(callerId, caller_lifetime) %>%
  count()

ggplot(data=lifetime, aes(x=caller_lifetime)) +
  geom_histogram(fill='brown', color='black')+
  labs(
    title = 'Distribution of Call Lifetimes',
    x = 'Years between First and Last Call',
    y= 'count'
  )


#distribution of calls made

calls_made <- log_data %>%
  group_by(callerId, noCallsMade) %>%
  count()

ggplot(calls_made, aes(x=noCallsMade)) +
  geom_histogram(color="black", fill="blue") +
  xlim(0,350) +
  labs(
    title = 'Distribution of calls made per individual over lifetime (Outliers Excluded) \n
Min. 1st Qu.  Median  Mean   3rd Qu.    Max. 
    3.0    45.0    69.0     99.9    106.0    7110.0 ',
    x = 'Total number of calls'
  )


content_listened <- filter(log_data, grepl("CONTENT",logInfo))
content_listened <- filter(content_listened , !grepl("CONTENT MENU",logInfo))
content_listened <- filter(content_listened , !grepl("CONTENT IS NOT AVAILABLE",logInfo))

#Creating a content#_played column
content_listened$content_played <- ifelse(str_detect(content_listened$logInfo, 'CONTENT PLAYED', negate = FALSE),1,0)
content_listened$replay_request <- ifelse(str_detect(content_listened$logInfo, 'CONTENT REPLAY REQUESTED', negate = FALSE),1,0)

content_played<-aggregate(content_listened$content_played,list(content_listened$callerId), FUN=sum)
?rename
content_played <- content_played %>% 
  dplyr::rename(
    con_play = x,
    callerId = Group.1
    )

content_replay<-aggregate(content_listened$replay_request,list(content_listened$callerId), FUN=sum)
content_replay <- content_replay %>% 
 dplyr::rename(
    con_replay = x,
    callerId = Group.1
    )

content_counts <- cbind(content_played, content_replay)

content_counts$adjusted_con <- content_counts$con_play-content_counts$con_replay

content_counts$callerId <- NULL

summary(content_counts$adjusted_con)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 -2.000   2.000   2.500   2.807   4.000   9.000 
#graphing the true distribution of content played
ggplot(content_counts, aes(x=adjusted_con)) +
  geom_histogram(color="black", fill="green") +
  xlim(0,100) +
  labs(
    title = 'Distribution of total Content listened to all Across all Calls (Outliers Excluded) \n
      Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   0.00    3.00    8.00   17.79   20.00  279.00 ',
    x = 'Total Content Listen Across Calls'
  )



# Getting the number of calls per person
calls_made <- log_data %>%
  dplyr::group_by(callId) %>%
  count()

calls_made_id <- log_data %>%
  dplyr::group_by(callId, callerId) %>%
  count()


#join between tables
content_ratio <- left_join(calls_made_id, content_counts,by="callerId")
content_ratio[is.na(content_ratio)] <- 0

content_ratio <- content_ratio %>%
  dplyr::group_by(callerId, con_play, con_replay, adjusted_con) %>%
  count()

content_ratio$ratio <- content_ratio$adjusted_con/content_ratio$n

summary(content_ratio$ratio)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  -2.00    0.00    1.00    1.69    3.00    9.00 
ggplot(content_ratio, aes(x=ratio)) +
  geom_histogram(color="black", fill="red") +
  xlim(0,2)+
  labs(
    title = 'Distribution of ratio of content listened to Calls (Outliers Excluded) \n
Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     
 0.0000  0.5614  1.0000  1.2500  1.5292 13.4000 ',
    x = 'Content to Call Ratio'
  )



sum(content_ratio$n)
[1] 1000

TOP MENU

Next, we want to Breakd down the initial Menu options and delve into the distributions of the selections that the farmer can make at a different state in the IVR System

For the first analysis, we looked at the distribution of the TOP MENU in the data. This comes in as follows:

INCOMING CALL STARTED –> WELCOME MESSAGE PLAYED –> ASSINGED TO EXPERIMENT (OPTIONAL) –> TOP MENU

TOP MENU

  • RAIN OPTION
  • HHI OPTION (household Irrigation)
  • RESET PROFILE OPTION
  • TOP MENU REPLAY
  • LIVESTOCK OPTION
  • COVID OPTION

Please note, we are unsure of the order these are presented. For other menus, we do have the order

Below, we have visualized the number of farmers, out of our sample, that in the life time of their calling history have accessed a given TOP MENU item at least once

Additionally, we also visualized this same selection divided by language to see if the patterns of seleciont are similar or different across langaugesv

#STARTING HERE IS FOR UNIQUE CALLERS
# filtering out top Menu keys

top_menu <-filter(log_data, grepl("TOP MENU",logInfo))

#cleaning the axis
top_menu$logInfo<- str_replace(top_menu$logInfo, "TOP MENU - ", "")
top_menu$logInfo<- str_replace(top_menu$logInfo, " PRESSED", "")
top_menu$logInfo<- str_replace(top_menu$logInfo, " PRESSED", "")
top_menu$logInfo<- str_replace(top_menu$logInfo, " SELECTED", "")

top_menu <- top_menu %>%
  group_by(callerId, logInfo, langId) %>%
  count()


ggplot(top_menu, aes(logInfo)) +
  theme(axis.text.x = element_text(angle = 30, hjust =1))+
  geom_bar()+
  labs(
    title = 'Distirution of TOP MENU items selected at least once by a unique caller',
    x = 'TOP MENU options'
  )


ggplot(top_menu, aes(langId, fill = logInfo)) +
  geom_bar()+
  labs(
    title = 'Distirution of Languages divided by TOP MENU option
    1 = Amharic, 2=Oromiffa, 3=Tigrigna, 4=Wolayitta, and 5=Sidamigna',
    x = 'Language'
  )


#STARTING HERE IS FOR UNIQUE CALLS

top_menu_call <-filter(log_data, grepl("TOP MENU",logInfo))

#cleaning the axis
top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, "TOP MENU - ", "")
top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, " PRESSED", "")
top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, " PRESSED", "")
top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, " SELECTED", "")

top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, "RAIN OPTION", "1 - RAIN OPTION")
top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, "HHI OPTION", "2 - HHI OPTION")
top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, "LIVESTOCK OPTION", "3 - LIVESTOCK OPTION")
top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, "COVID OPTION", "4 - COVID OPTION")
top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, "RESET PROFILE OPTION", "\\* - RESET PROFILE")
top_menu_call$logInfo<- str_replace(top_menu_call$logInfo, "TOP MENU REPLAYED", "\\# - TOP MENU REPLAYED")

top_menu_call <- top_menu_call %>%
  group_by(callId, logInfo) %>%
  count()

top_menu_call<- top_menu_call[match(unique(top_menu_call$callId), top_menu_call$callId),]

ggplot(top_menu_call, aes(x=fct_infreq(logInfo))) +
  theme(axis.text.x = element_text(angle = 25, hjust =1))+
  geom_bar(color='black', fill='red')+
  geom_text(stat='count', aes(label=..count..), vjust=-1)+
  ylim(0,6500)+
  labs(
    title = 'Distirution of Top Menu Options Selected per Call with Number Pressed Indicated',
    x = 'Top Menu Options',
    y='Number of Calls'
  )

unique(top_menu_call$callId)
[1] NA
class(log_data)
[1] "data.frame"

As we can easily see, the RAIN options and the HHI option dominate the choices from the top Menu. So, we decided to dive deeper into each of these menus to see if there are any outlier selections that are deep within the system. Additionally, ths distribution across languages seems to be fairly consistent at face value. We can run tests in the future, but for EDA this will be adequate. For 3/4 langauge options - having more data would be apprecaited

RAIN MENU

INCOMING CALL STARTED –> WELCOME MESSAGE PLAYED –> RANDOM EXPERIMENT –> TOP MENU –> RAIN MENU

Here, we look at the breakdown of individuals who have selected a given option in the rain menu at least once. In the data, MAIN MENU == RAIN MENU.

RAIN MENU

  • PRE PLANTING OPTION
  • PLANTING OPTION
  • CROP PROTECTION OPTION
  • FERTILIZGER SIDE DREESSING
  • POST HARVEST AND PROCESSING
  • REPEAT RAIN MENU
  • RETURN TO TOP MENU
  • INVALID KEY PRESSED (ADDITIONAL OUTCOME)
# Pulling out the rain Menu By CALLLER

#RAIN == HHI_RAIN
rain_menu <- filter(log_data, grepl("MAIN MENU - ",logInfo))
rain_menu <- filter(rain_menu, !grepl("LIVESTOCK MAIN MENU",logInfo))
rain_menu <- filter(rain_menu, !grepl("HHI MAIN MENU",logInfo))
rain_menu <- filter(rain_menu, !grepl("COVID-19 MAIN MENU",logInfo))

#grouping the observations
rain_menu <-rain_menu %>%
  group_by(callerId, logInfo, langId) %>%
  count()

rain_menu$logInfo<- str_replace(rain_menu$logInfo, "MAIN MENU - ", "")
rain_menu$logInfo<- str_replace(rain_menu$logInfo, " SELECTED", "")
rain_menu$logInfo<- str_replace(rain_menu$logInfo, " PRESSED", "")
rain_menu$logInfo<- str_replace(rain_menu$logInfo, " OPTION", "")

#plotting rain menu breakdown
ggplot(data=rain_menu, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 30, hjust =1))+
  geom_bar(fill='blue')+
  labs(
    title = 'Breakdown for Individuals By Content Selected at least Once from the rain menu',
    x = 'Content Selected',
    y= 'count'
  )




#DOING IT BY CALL!!!!
rain_menu_call <- filter(log_data, grepl("MAIN MENU - ",logInfo))
rain_menu_call <- filter(rain_menu_call, !grepl("LIVESTOCK MAIN MENU",logInfo))
rain_menu_call <- filter(rain_menu_call, !grepl("HHI MAIN MENU",logInfo))
rain_menu_call <- filter(rain_menu_call, !grepl("COVID-19 MAIN MENU",logInfo))

#grouping the observations
rain_menu_call<-rain_menu_call %>%
  group_by(callId, logInfo,) %>%
  count()

rain_menu_call<- rain_menu_call[match(unique(rain_menu_call$callId), rain_menu_call$callId),]

rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, "MAIN MENU - ", "")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, " SELECTED", "")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, " PRESSED", "")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, " OPTION", "")


#FIxing the HHI menu and adding numbeers
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, "PRE PLANTING", "1 - PREPLZNTING")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, "PLANTING", "2 - PLANTING")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, "1 - PREPLZNTING", "1 - PREPLANTING")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, "CROP PROTECTION", "3 - CROP PROTECTION")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, "FERTILIZER SIDE DRESSING", "4 - FERTILIZER DRESSING")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, "POST HARVEST AND PROCESSING", "5 - POST HARVEST/PROCESSING")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, "GO TO MAIN MENU", "* - GO TO MAIN MENU")
rain_menu_call$logInfo<- str_replace(rain_menu_call$logInfo, "MAIN MENU REPLAYED", "# - MAIN MENU REPLAYED")

#plotting rain menu breakdown
ggplot(data=rain_menu_call, aes(x=fct_infreq(logInfo))) +
  theme(axis.text.x = element_text(angle = 25, hjust =1))+
  geom_bar(color='black', fill='blue',position = position_dodge( 0.3))+
  geom_text(stat='count', aes(label=..count..), vjust=-1)+
  ylim(0,3250)+
  labs(
    title = 'Distirution of Rain Menu Options Selected per Call',
    x = 'Rain Menu Options',
    y='Number of Calls'
  )


#GETTING HHI MENU PER CALL
HHI_menu_call <- filter(log_data, grepl("HHI MAIN MENU - ",logInfo))

#grouping the observations
HHI_menu_call<-HHI_menu_call %>%
  group_by(callId, logInfo,) %>%
  count()

HHI_menu_call<- HHI_menu_call[match(unique(HHI_menu_call$callId), HHI_menu_call$callId),]

HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "HHI MAIN MENU - ", "")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, " SELECTED", "")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, " PRESSED", "")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, " OPTION", "")


#FIxing the HHI menu and adding numbeers
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "PRE PLANTING", "1 - PREPLANTING")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "PLANTING AND TRANSPLANTING", "2 - PLANTING/TRANSPLANTING")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "HARROWING AND EARTHNING", "3 - HARROWING/EARTHNING")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "IRRIGATING CROPS", "4 - IRRIGATING CROPS")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "PROTECTING CROPS", "5 - PROTECTING CROPS")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "APPLYING FERTILIZER", "6 - APPLYING FERTILIZER")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "HARVESTING AND PROCESSING", "7 - HARVESTING/PROCESSING")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "GO TO MAIN MENU", "* - GO TO MAIN MENU")
HHI_menu_call$logInfo<- str_replace(HHI_menu_call$logInfo, "HHI MAIN MENU REPLAYED", "# - HHI MAIN MENU REPLAYED")


#plotting rain menu breakdown
ggplot(data=HHI_menu_call, aes(x=fct_infreq(logInfo))) +
  theme(axis.text.x = element_text(angle = 30, hjust =1))+
  geom_bar(color='black', fill='green',position = position_dodge( 0.3))+
  geom_text(stat='count', aes(label=..count..), vjust=-1)+
  ylim(0,1300)+
  labs(
    title = 'Distirution of HHI Menu Options Selected per Call',
    x = 'HHI Menu Options',
    y='Number of Calls'
  )

We can see that the pre-planting menu, which still has over 75% of unique users accesss it at least once expereinces incredibly high usage. So, we now dive into this menu. We will breakdown conent selection by language and overall

RAIN MENU/PRE PLANTING MENU

INCOMING CALL STARTED –> WELCOME MESSAGE PLAYED –> RANDOM EXPERIMENT –>
TOP MENU –> RAIN MENU –> PRE PLANTING MENU

Please note, the pre planting menu under the rain menu is referred to as MENU 1 in the data

PRE PLANTING MENU

  • LAND PREPARATION
  • SEED VARIETY
  • REPEAT MENU
  • GO TO MAIN MENU (RAIN MENU)
  • INVALID KEY (ADDITIONAL OUTCOME)


#filtering out MENU 1 options as the pre planting
MENU_1 <- filter(log_data, grepl("MENU 1",logInfo))
MENU_1 <- filter(MENU_1, !grepl("HHIMENU 1",logInfo))
MENU_1 <- filter(MENU_1, !grepl("APICULTURE MENU",logInfo))
MENU_1 <- filter(MENU_1, !grepl("APICULTURE SUB4 MENU",logInfo))
MENU_1 <- filter(MENU_1, !grepl("DAIRY MENU",logInfo))
MENU_1 <- filter(MENU_1, !grepl("SMALL-SCALE SUB5 MENU",logInfo))
MENU_1 <- filter(MENU_1, !grepl("DAIRY SUB2 MENU",logInfo))
MENU_1 <- filter(MENU_1, !grepl("FATTENING MANU",logInfo))

MENU_1 <- filter(MENU_1, !grepl("FATTENING SUB1 MENU",logInfo))
MENU_1 <- filter(MENU_1, !grepl("FATTENING SUB2 MENU",logInfo))
MENU_1 <- filter(MENU_1, !grepl("HOUSEHOLD MENU",logInfo))
MENU_1 <- filter(MENU_1, !grepl("HOUSEHOLD SUB1 MENU ",logInfo))


MENU_1 <- MENU_1 %>%
  group_by(callerId, logInfo, langId) %>%
  count()

MENU_1$logInfo<- str_replace(MENU_1$logInfo, "MENU 1 - ", "")
MENU_1$logInfo<- str_replace(MENU_1$logInfo, " PRESSED", "")
MENU_1$logInfo<- str_replace(MENU_1$logInfo, " SELECTED", "")

# plotting
ggplot(data=MENU_1, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 25, hjust= 1))+
  geom_bar(fill='cyan')+
  labs(
    title = 'Individuals By Content Selected at least Once from 
    RAIN MENU/PRE PLANTING OPTION',
    x = 'Content Selected',
    y= 'count'
  )

NA
NA
NA

RAIN MENU/PRE PLANTING MENU/LAND PREPARATION

We continue our pattern of following the most accessed submenu from the previous subment - land preparation! This is also the bottom of a tree. We will breakdown conent selection by language and overall

INCOMING CALL STARTED –> WELCOME MESSAGE PLAYED –> RANDOM EXPERIMENT –>
TOP MENU –> RAIN MENU –> PRE PLANTING MENU –> LAND PREPARATION

LAND PREPARATION

  • BARLEY
  • MAIZE
  • SORGHUM
  • TEF
  • WHEAT
  • SESAME
  • FAVA BEAN
  • CHICKPEA
  • COMMON BEAN
  • COTTON

ORDER UNKOWN:

  • RICE
  • DURAME WHEAT
  • LENTIL
  • MALT BARLEY
#GETTING THE CROP MENU FROM MENU 1 (rain/preplanting/land preparation sub menu)
land_prep <- filter(log_data, grepl("CONTENT PLAYED - LAND PREPARATION - ",logInfo))

land_prep_final <- land_prep %>%
  group_by(callerId, logInfo, langId) %>%
  count()

land_prep_final$logInfo<- str_replace(land_prep_final$logInfo, "CONTENT PLAYED - LAND PREPARATION -", "")

ggplot(data=land_prep_final, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 45, hjust=2))+
  geom_bar()+
  labs(
    title = 'RAIN MENU/PRE PLANTING/LAND PREPARATION
    content actually played by language',
    x = 'Content Played',
    y= 'count'
  )



#get rid of the language breakdown
land_prep_no_lang <- land_prep_final

land_prep_no_lang$logInfo<- str_replace(land_prep_no_lang$logInfo, "- AMHARIC", "")
land_prep_no_lang$logInfo<- str_replace(land_prep_no_lang$logInfo, "- OROMIFFA", "")
land_prep_no_lang$logInfo<- str_replace(land_prep_no_lang$logInfo, "- TIGRIGNA", "")
land_prep_no_lang$logInfo<- str_replace(land_prep_no_lang$logInfo, "- WOLAYITTA", "")
land_prep_no_lang$logInfo<- str_replace(land_prep_no_lang$logInfo, "- WOLAYTIGNA", "")
land_prep_no_lang$logInfo<- str_replace(land_prep_no_lang$logInfo, "- SIDAMIGNA", "")

ggplot(land_prep_no_lang, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 90))+
  geom_bar()+
  labs(
    title = 'RAIN MENU/PRE PLANTING/LAND PREPARATION
    content played overall',
    x = 'Content Played',
    y= 'count'
  )


ggplot(land_prep_no_lang, aes(langId, fill = logInfo)) +
  geom_bar()+
  labs(
    title = 'ALTERNATIVE RAIN MENU/PRE PLANTING/LAND PREPARATION
    content actually played by language
    1 = Amharic, 2=Oromiffa, 3=Tigrigna, 4=Wolayitta, and 5=Sidamigna
    ',
    x = 'Language'
  )

BIG TAKEAWAY: 35% of users end up accessing the maize menu at some point! Wheat, Tef, Sorghum, and Barley also appear to be qualitatively significant

There is no menu to go deeper in, so let’s go back up a level and check to see if other branches have a lot of access

RAIN MENU/PRE PLANTING MENU/SEED VARIETY

INCOMING CALL STARTED –> WELCOME MESSAGE PLAYED –> RANDOM EXPERIMENT –>
TOP MENU –> RAIN MENU –> PRE PLANTING MENU –> SEED VARIETY

SEED VARIETY

  • BARLEY
  • MAIZE
  • SORGHUM
  • TEF
  • WHEAT
  • SESAME
  • FAVA BEAN
  • CHICKPEA
  • COMMON BEAN
#GETTING THE CROP MENU FROM MENU 1 (rain/preplanting/seed variety sub menu)
seed_variety <- filter(log_data, grepl("CONTENT PLAYED - SEED VARITY",logInfo))

seed_variety_final <- seed_variety %>%
  group_by(callerId, logInfo, langId) %>%
  count()

seed_variety_final$logInfo<- str_replace(seed_variety_final$logInfo, "CONTENT PLAYED - SEED VARITY - ", "")

ggplot(data=seed_variety_final, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 45, hjust=1))+
  geom_bar()+
  labs(
    title = 'RAIN MENU/PRE PLANTING/SEED VARIETY
    content actually played by language',
    x = 'Content Selected',
    y= 'count'
  )



#get rid of the language breakdown
seed_variety_no_lang <- seed_variety_final

seed_variety_no_lang$logInfo<- str_replace(seed_variety_no_lang$logInfo, "- AMHARIC", "")
seed_variety_no_lang$logInfo<- str_replace(seed_variety_no_lang$logInfo, "- OROMIFFA", "")
seed_variety_no_lang$logInfo<- str_replace(seed_variety_no_lang$logInfo, "- TIGRIGNA", "")
seed_variety_no_lang$logInfo<- str_replace(seed_variety_no_lang$logInfo, "- WOLAYITTA", "")
seed_variety_no_lang$logInfo<- str_replace(seed_variety_no_lang$logInfo, "- WOLAYTIGNA", "")
seed_variety_no_lang$logInfo<- str_replace(seed_variety_no_lang$logInfo, "- SIDAMIGNA", "")

#alternative with langauge view
ggplot(seed_variety_no_lang, aes(langId, fill = logInfo)) +
  geom_bar()+
  labs(
    title = 'ALTERNATIVE RAIN MENU/PRE PLANTING/SEE VARIETY
    content actually played by language
    1 = Amharic, 2=Oromiffa, 3=Tigrigna, 4=Wolayitta, and 5=Sidamigna
    ',
    x = 'Language'
  )


#no language - overall
ggplot(seed_variety_no_lang, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 30, hjust=1))+
  geom_bar()+
  labs(
    title = 'RAIN MENU/PRE PLANTING/seed variety
    content actually played',
    x = 'Content Selected',
    y= 'count'
  )

NA
NA

We have mostly exhausted the pre-planting option menu, and if we go back up to the original rain menu (aka MAIN MENU), we can see that planting also has a large porportion of users - over half

RAIN MENU/PLANTING MENU

INCOMING CALL STARTED –> WELCOME MESSAGE PLAYED –> RANDOM EXPERIMENT –>
TOP MENU –> RAIN MENU –> PLANTING MENU

The planting option as a subsection of the rain option is known as MENU 2 in the data

PLANTING MENU

  • SEED RATE
  • SOIL DEPTH PLANTING
  • TRANSPLANTING
  • MOISTURE CONSERVATION
  • FERTILIZER APPLICATION
  • REPLAY MENY
  • RETURN TO RAIN MENY
  • INVALID KEY (ADDITIONAL OUTCOME)
#PLANTING OPTION - second most accessed MENU 2
MENU_2 <- filter(log_data, grepl("MENU 2",logInfo))
MENU_2 <- filter(MENU_2, !grepl("HHIMENU 2",logInfo))
MENU_2 <- filter(MENU_2, !grepl("APICULTURE MENU",logInfo))
MENU_2 <- filter(MENU_2, !grepl("APICULTURE SUB2 MENU",logInfo))
MENU_2 <- filter(MENU_2, !grepl("DAIRY MENU",logInfo))
MENU_2 <- filter(MENU_2, !grepl("FATTENING MANU",logInfo))

MENU_2 <- MENU_2 %>%
  group_by(callerId, logInfo, langId) %>%
  count()

#cleaning
MENU_2$logInfo<- str_replace(MENU_2$logInfo, "MENU 2 - ", "")
MENU_2$logInfo<- str_replace(MENU_2$logInfo, " SELECTED", "")
MENU_2$logInfo<- str_replace(MENU_2$logInfo, " PRESSED", "")
MENU_2$logInfo<- str_replace(MENU_2$logInfo, " OPTION", "")


#plotting
ggplot(data=MENU_2, aes(x=fct_infreq(logInfo))) +
  theme(axis.text.x = element_text(angle = 45, hjust=1))+
  geom_bar(fill='olivedrab')+
  labs(
    title = 'Individuals By Content Selected at least Once from 
    RAIN MENU/PLANTING OPTION',
    x = 'Content Selected',
    y= 'count'
  )

As per usual, we will go into the most common selection: seed rate!

RAIN MENU/PLANTING MENU/SEED RATE

INCOMING CALL STARTED –> WELCOME MESSAGE PLAYED –> RANDOM EXPERIMENT –>
TOP MENU –> RAIN MENU –> PLANTING MENU –> SEED RATE

SEED RATE

  • BARLEY
  • MAIZE
  • SORGHUM
  • TEF
  • WHEAT
  • SESAME
  • FAVA BEAN
  • CHICKPEA
  • COMMON BEAN
  • COTTON

ORDER UNKOWN:

  • RICE
  • DURAME WHEAT
  • LENTIL
  • MALT BARLEY
seed_rate <- filter(log_data, grepl("CONTENT PLAYED - SEED RATE",logInfo))

seed_rate_final <- seed_rate %>%
  group_by(callerId, logInfo, langId) %>%
  count()

seed_rate_final$logInfo<- str_replace(seed_rate_final$logInfo, "CONTENT PLAYED - SEED RATE -", "")

ggplot(data=seed_rate_final, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 45,hjust=1))+
  geom_bar()+
  labs(
    title = 'RAIN MENU/PLANTING/SEED RATE
    content actually played by language',
    x = 'Content Selected',
    y= 'count'
  )


#get rid of the language breakdown
seed_rate_no_lang <- seed_rate_final

seed_rate_no_lang$logInfo<- str_replace(seed_rate_no_lang$logInfo, "- AMHARIC", "")
seed_rate_no_lang$logInfo<- str_replace(seed_rate_no_lang$logInfo, "- OROMIFFA", "")
seed_rate_no_lang$logInfo<- str_replace(seed_rate_no_lang$logInfo, "- TIGRIGNA", "")
seed_rate_no_lang$logInfo<- str_replace(seed_rate_no_lang$logInfo, "- WOLAYITTA", "")
seed_rate_no_lang$logInfo<- str_replace(seed_rate_no_lang$logInfo, "- WOLAYTIGNA", "")
seed_rate_no_lang$logInfo<- str_replace(seed_rate_no_lang$logInfo, "- SIDAMIGNA", "")

#alternative with langauge view
ggplot(seed_rate_no_lang, aes(langId, fill = logInfo)) +
  geom_bar()+
  labs(
    title = 'ALTERNATIVE RAIN MENU/PLANTING/SEED RATE
    content actually played by language
    1 = Amharic, 2=Oromiffa, 3=Tigrigna, 4=Wolayitta, and 5=Sidamigna
    ',
    x = 'Language'
  )

#no language
ggplot(seed_rate_no_lang, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 45, hjust=1))+
  geom_bar()+
  labs(
    title = 'RAIN MENU/PLANTING/SEED RATE
    content actually played',
    x = 'Content Selected',
    y= 'count'
  )

crop_menu <- log_data %>%
  filter(grepl("CROP MENU - ",logInfo)) %>%
  filter(!grepl("HHI",logInfo)) %>%
  filter(!grepl("REPLAYED",logInfo))

crop_menu <- crop_menu %>%
  group_by(callerId, logInfo, langId) %>%
  count()

crop_menu$logInfo<- str_replace(crop_menu$logInfo, "CROP MENU - ", "")
crop_menu$logInfo<- str_replace(crop_menu$logInfo, " SELECTED", "")
crop_menu$logInfo<- str_replace(crop_menu$logInfo, "GO TO", "")


ggplot(crop_menu, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown',
    x = 'Crops',
    y= 'count'
  )


ggplot(crop_menu, aes(langId, fill = logInfo)) +
  geom_bar()+
  labs(
    title = 'CROP MENU BY LANGUAGE
    1 = Amharic, 2=Oromiffa, 3=Tigrigna, 4=Wolayitta, and 5=Sidamigna
    ',
    x = 'Language'
  )

num_crop_types <- data.frame(as.numeric(table(crop_menu$callerId)))
num_crop_types$frequencies <- num_crop_types$as.numeric.table.crop_menu.callerId.

summary(num_crop_types$frequencies)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   1.000   2.000   2.428   3.000   6.000 
ggplot(num_crop_types, aes(frequencies)) +
  geom_histogram(color="black", fill="red") +
  labs(
    title = 'Distribution of number crops ever selected by individual \n
      Min.  1st Qu.  Median    Mean   3rd Qu.    Max. 
  1.000     2.000     4.000      4.915     7.000     15.000 ',
    x = 'Number of crops selected '
  )

#GETTING BOTH THE CROP MENUS for both rain and hhi
rain_crop_menu <- filter(log_data, grepl("CROP MENU - ",logInfo))
rain_crop_menu <- filter(rain_crop_menu, !grepl("HHI",logInfo))

rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "CROP MENU - ", "")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, " SELECTED", "")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, " PTION", "OPTION")
table(rain_crop_menu$logInfo)

         BARLEY OPTION        CHICKPEA OPTION      COMMON BEANOPTION          COTTON OPTION     CROP MENU REPLAYED     DUREM WHEAT OPTION 
                   454                      6                      2                     15                    137                      2 
      FAVA BEAN OPTION GO TO MAIN MENU OPTION    INVALID KEY PRESSED          LENTIL OPTION           MAIZE OPTION     MALT BARLEY OPTION 
                     7                    121                    190                      1                    508                      9 
           RICE OPTION          SESAME OPTION         SORGHUM OPTION             TEF OPTION           WHEAT OPTION 
                     1                      7                    153                    322                    326 
#ADDING THE NUMBERS
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "BARLEY OPTION", "1 - BARLEY OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "MAIZE OPTION", "2 - MAIZE OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "SORGHUM OPTION", "3 - SORGHUM OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "TEF OPTION", "4 - TEF OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "WHEAT OPTION", "5 - WHEAT OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "SESAME OPTION", "6 - SESAME OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "FAVA BEAN OPTION", "7 - FAVA BEAN OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "CHICKPEA OPTION", "8 - CHICKPEA OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "COMMON BEANOPTION", "9 - COMMON BEAN OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "COTTON OPTION", "10 - COTTON OPTION")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "CROP MENU REPLAYED", "# - CROP MENU REPLAYED")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "GO TO MAIN MENU OPTION", "* - GO TO MAIN MENU OPTION")

#fixes
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "MALT 1 - ", "MALT ")
rain_crop_menu$logInfo<- str_replace(rain_crop_menu$logInfo, "DUREM 5 - ", "DUREM ")



#plotting rain
ggplot(rain_crop_menu, aes(x=fct_infreq(logInfo))) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar(fill='black')+
  geom_text(stat='count', aes(label=..count..), vjust=-1)+
  ylim(0,3200)+
  labs(
    title = 'Rain Crop menu Total Selections with Button Choices',
    x = 'Crops',
    y= 'count'
  )



#getting the HHI MENU
hhi_crop_menu <- filter(log_data, grepl("HHICROP MENU - ",logInfo))
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "HHICROP MENU - ", "")
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, " SELECTED", "")
table(hhi_crop_menu$logInfo)

         CARROT OPTION     CROP MENU REPLAYED          GARLIC OPTION GO TO MAIN MENU OPTION    HEAD CABBAGE OPTION    INVALID KEY PRESSED 
                    14                      5                     10                      7                      3                      1 
          ONION OPTION           PAPER OPTION          POTATO OPTION          TOMATO OPTION 
                    14                      4                     17                      7 
#ADDING THE NUMBERS
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "POTATO OPTION", "1 - POTATO OPTION")
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "CARROT OPTION", "2 - CARROT OPTION")
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "ONION OPTION", "3 - ONION OPTION")
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "GARLIC OPTION", "4 - GARLIC OPTION")
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "TOMATO OPTION", "5 - TOMATO OPTION")
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "PAPER OPTION", "6 - PEPPER OPTION")
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "HEAD CABBAGE OPTION", "7 - HEAD CABBAGE OPTION")
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "CROP MENU REPLAYED", "# - CROP MENU REPLAYED")
hhi_crop_menu$logInfo<- str_replace(hhi_crop_menu$logInfo, "GO TO MAIN MENU OPTION", "* - GO TO MAIN MENU OPTION")

#plotting HHI
ggplot(hhi_crop_menu, aes(x=fct_infreq(logInfo))) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar(fill='brown')+
  geom_text(stat='count', aes(label=..count..), vjust=-1)+
  ylim(0,1750)+
  labs(
    title = 'HHI Crop Menu Total Selections with Button Choices',
    x = 'Crops',
    y= 'count'
  )

#What about a nice crop breakdown per month?


crop_month <- log_data %>%
  filter(grepl("CROP MENU - ",logInfo)) %>%
  filter(!grepl("HHI",logInfo)) %>%
  filter(!grepl("REPLAYED",logInfo))

crop_month <- crop_month %>%
  group_by(callerId, logInfo,month) %>%
  count()

crop_month$logInfo<- str_replace(crop_month$logInfo, "CROP MENU - ", "")
crop_month$logInfo<- str_replace(crop_month$logInfo, " SELECTED", "")
crop_month$logInfo<- str_replace(crop_month$logInfo, "GO TO", "")


crop_track <- crop_month %>%
  filter(month == 1)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown Jan',
    x = 'Crops',
    y= 'count'
  )

  
crop_track <- crop_month %>%
  filter(month == 2)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown feb',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 3)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown mar',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 4)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown april',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 5)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown may',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 6)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown june',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 7)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown july',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 8)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown aug',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 9)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown sep',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 10)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown oct',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 11)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown nov',
    x = 'Crops',
    y= 'count'
  )

crop_track <- crop_month %>%
  filter(month == 12)
ggplot(crop_track, aes(x=logInfo)) +
  theme(axis.text.x = element_text(angle = 60, hjust =1, size = 7))+
  geom_bar()+
  labs(
    title = 'Crop menu breakdown dec',
    x = 'Crops',
    y= 'count'
  )

NA
NA
LS0tCnRpdGxlOiAiUEFELUFUQSBDYWxsIExvZyBBbmFseXNpcyIKb3V0cHV0OgogIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKIyMjIyBMaWJyYXJpZXMgdXNlZCBpbiB0aGUgUHJvamVjdCBhbmQgdXBsb2FkaW5nIGRhdGEKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShkcGx5cikKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHN2TWlzYykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGd0YWJsZSkKbGlicmFyeSgiZ2dwdWJyIikKCmxvZ19kYXRhIDwtIHJlYWRfY3N2KCJ+L0Rlc2t0b3AvUEFFL2dpdGh1Yi9kYXRhL2xvZ0RhdGEuY3N2IikKbG9nX2RhdGEgPC0gcmVhZF9jc3YoIn4vRGVza3RvcC9QQUUvZ2l0aHViL2RhdGEvYmVuRGF0YV93ZWFrQ2FsbGVycy5jc3YiKQoKbG9nX2RhdGFfc2F2ZXIgPC0gbG9nX2RhdGEKCmxvZ19kYXRhIDwtIHVuaXF1ZShsb2dfZGF0YSkKCmxvZ19kYXRhJGxvZ0luZm8gPC0gc3RyX3JlcGxhY2UobG9nX2RhdGEkbG9nSW5mbywgIiAgIiwgIiAiKQoKI01BS0UgSVQgQUxMIFVQUEVSISEhCgpsb2dfZGF0YSRsb2dJbmZvIDwtIHRvdXBwZXIobG9nX2RhdGEkbG9nSW5mbykKCiMjIyBHRVRUSU5HIFRIRSBEQVRFIE1PTlRIIEFORCBZRUFSIElGIEkgV0FOVCEhIQpleHRyYWN0ZGF0ZSA8LSBmdW5jdGlvbihkYXRlKSB7CiAgICBkYXkgPC0gZm9ybWF0KGRhdGUsIGZvcm1hdD0iJWQiKQogICAgbW9udGggPC0gZm9ybWF0KGRhdGUsIGZvcm1hdD0iJW0iKQogICAgeWVhciA8LSBmb3JtYXQoZGF0ZSwgZm9ybWF0PSIlWSIpCgogICAgY2JpbmQoZGF5LCBtb250aCwgeWVhcikKfQoKI21ha2luZyBmaXJzdCBjYWxscwpmaXJzdF9jYWxsPC1leHRyYWN0ZGF0ZShsb2dfZGF0YSRjYWxsVGltZSkKCgojbWFraW5nIGxhc3QgY2FsbApsYXN0X2RheSA8LXN1YnN0cihsb2dfZGF0YSRldmVudFRpbWUsIDksIDEwKQpsYXN0X21vbnRoIDwtIHN1YnN0cihsb2dfZGF0YSRldmVudFRpbWUsIDYsIDcpCmxhc3RfeWVhciA8LXN1YnN0cihsb2dfZGF0YSRldmVudFRpbWUsIDEsIDQpCgpsb2dfZGF0YTwtY2JpbmQobG9nX2RhdGEsIGZpcnN0X2NhbGwsbGFzdF9kYXksbGFzdF9tb250aCxsYXN0X3llYXIpCgojQ29udmVydGluZyBjb2x1bW5zIHRvIG51bWVyaWMKbG9nX2RhdGEkZGF5IDwtYXMubnVtZXJpYyhsb2dfZGF0YSRkYXkpCmxvZ19kYXRhJGxhc3RfZGF5IDwtIGFzLm51bWVyaWMobG9nX2RhdGEkbGFzdF9kYXkpCmxvZ19kYXRhJG1vbnRoIDwtYXMubnVtZXJpYyhsb2dfZGF0YSRtb250aCkKbG9nX2RhdGEkbGFzdF9tb250aCA8LSBhcy5udW1lcmljKGxvZ19kYXRhJGxhc3RfbW9udGgpCmxvZ19kYXRhJHllYXIgPC0gYXMubnVtZXJpYyhsb2dfZGF0YSR5ZWFyKQpsb2dfZGF0YSRsYXN0X3llYXIgPC0gYXMubnVtZXJpYyhsb2dfZGF0YSRsYXN0X3llYXIgKQoKCmxvZ19kYXRhJHllYXIgPC0gbG9nX2RhdGEkeWVhciArbG9nX2RhdGEkbW9udGgvMTIKbG9nX2RhdGEkbGFzdF95ZWFyIDwtIGxvZ19kYXRhJGxhc3RfeWVhciArIGxvZ19kYXRhJGxhc3RfbW9udGgvMTIKCmxvZ19kYXRhJGNhbGxlcl9saWZldGltZSA8LSBsb2dfZGF0YSRsYXN0X3llYXIgLSBsb2dfZGF0YSR5ZWFyCmBgYAoKKkNtZCtPcHRpb24rSSouCgogKkNtZCtTaGlmdCtLKiAKIAojIyMgUFJFTElNSU5BUlkgRElTVFJJQlVUSU9OUwogCioqSW4gdGhpcyBzZWN0aW9uLCB3ZSBkaXNwbGF5IHNvbWUgb2YgdGhlIGJhc2ljIGRpc3RyaWJ1dGlvbnMgb2YgdGhlIGRhdGEgaW5jbHVkaW5nIGxhbmd1YWdlcywgdG90YWwgbGlmZWV0aW1lIG9mIGEgZ2l2ZW4gY2FsbGVyLCBjb2xscyBtYWRlLCBjb250ZW50IGFjY2Vzc2VkLCBhbmQgdGhlIHJhdGlvIG9mIGNvbnRlbnQgbGlzdGVuZWQgdG8gY2FsbHMgbWFkZS4qKgoKKipCYXNlZCBvbiB0aGUgZ3JhcGhzIGJlbG93LCB3ZSBhcmUgbmVydm91cyB0aGF0IHNvbWUgb2YgdGhlIGRhdGEgaXMgbm90IHJhbmRvbSBnaXZlbiB0aGUgaW5jcmVkaWJseSBoaWdoIHJhdGlvIGZvciBjb250ZW50IGxpc3RlbmVkIHRvIGNhbGxzIG1hZGUsIGJ1dCBnaXZlbiB0aGF0IHRoZSBkYXRhIGlzIGRpc3RyaWJ1dGVkIGZhaXJseSBldmVubHkgYWNyb3NzIHRoZWUgZGlmZmVyZW50IGdyYXBocywgd2UgYXJlIHVuc3VyZSoqCgpgYGB7cn0KbGFuZ19zcG9rZW4gPC0gbG9nX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY2FsbGVySWQsIGxhbmdJZCkgJT4lCiAgY291bnQoKQoKI0Rpc3RyaWJ1dGlvbiBvZiBsYW5ndWFnZXMgc3Bva2VuCmdncGxvdChkYXRhPWxhbmdfc3Bva2VuLCBhZXMoeD1sYW5nSWQpKSArCiAgZ2VvbV9iYXIoZmlsbD0ncmVkJykrCiAgZ2VvbV90ZXh0KHN0YXQ9J2NvdW50JywgYWVzKGxhYmVsPS4uY291bnQuLi8xNjQ0NSksIHZqdXN0PS0xKSsKICB5bGltKDAsNjAwKSsKICBsYWJzKAogICAgdGl0bGUgPSAnRGlzdHJpYnV0aW9uIG9mIExhbmd1YWdlcyBieSBDYWxsZXIKICAgIDEgPSBBbWhhcmljLCAyPU9yb21pZmZhLCAzPVRpZ3JpZ25hLCA0PVdvbGF5aXR0YSwgYW5kIDU9U2lkYW1pZ25hJywKICAgIHggPSAnTGFuZ3VhZ2UnLAogICAgeT0gJ2NvdW50JwogICkKCgojRGlzdHJpYnV0aW9uIG9mIHRpbWUgZGlmZmVyZW5jZSBiZXd0d2VlbiBmaXJzdCBhbmQgbGFzdCBjYWxsCgpsaWZldGltZTwtIGxvZ19kYXRhICU+JQogIGdyb3VwX2J5KGNhbGxlcklkLCBjYWxsZXJfbGlmZXRpbWUpICU+JQogIGNvdW50KCkKCmdncGxvdChkYXRhPWxpZmV0aW1lLCBhZXMoeD1jYWxsZXJfbGlmZXRpbWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oZmlsbD0nYnJvd24nLCBjb2xvcj0nYmxhY2snKSsKICBsYWJzKAogICAgdGl0bGUgPSAnRGlzdHJpYnV0aW9uIG9mIENhbGwgTGlmZXRpbWVzJywKICAgIHggPSAnWWVhcnMgYmV0d2VlbiBGaXJzdCBhbmQgTGFzdCBDYWxsJywKICAgIHk9ICdjb3VudCcKICApCgojZGlzdHJpYnV0aW9uIG9mIGNhbGxzIG1hZGUKCmNhbGxzX21hZGUgPC0gbG9nX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY2FsbGVySWQsIG5vQ2FsbHNNYWRlKSAlPiUKICBjb3VudCgpCgpnZ3Bsb3QoY2FsbHNfbWFkZSwgYWVzKHg9bm9DYWxsc01hZGUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oY29sb3I9ImJsYWNrIiwgZmlsbD0iYmx1ZSIpICsKICB4bGltKDAsMzUwKSArCiAgbGFicygKICAgIHRpdGxlID0gJ0Rpc3RyaWJ1dGlvbiBvZiBjYWxscyBtYWRlIHBlciBpbmRpdmlkdWFsIG92ZXIgbGlmZXRpbWUgKE91dGxpZXJzIEV4Y2x1ZGVkKSBcbgpNaW4uIDFzdCBRdS4gIE1lZGlhbiAgTWVhbiAgIDNyZCBRdS4gICAgTWF4LiAKICAgIDMuMCAgICA0NS4wICAgIDY5LjAgICAgIDk5LjkgICAgMTA2LjAgICAgNzExMC4wICcsCiAgICB4ID0gJ1RvdGFsIG51bWJlciBvZiBjYWxscycKICApCgpjb250ZW50X2xpc3RlbmVkIDwtIGZpbHRlcihsb2dfZGF0YSwgZ3JlcGwoIkNPTlRFTlQiLGxvZ0luZm8pKQpjb250ZW50X2xpc3RlbmVkIDwtIGZpbHRlcihjb250ZW50X2xpc3RlbmVkICwgIWdyZXBsKCJDT05URU5UIE1FTlUiLGxvZ0luZm8pKQpjb250ZW50X2xpc3RlbmVkIDwtIGZpbHRlcihjb250ZW50X2xpc3RlbmVkICwgIWdyZXBsKCJDT05URU5UIElTIE5PVCBBVkFJTEFCTEUiLGxvZ0luZm8pKQoKI0NyZWF0aW5nIGEgY29udGVudCNfcGxheWVkIGNvbHVtbgpjb250ZW50X2xpc3RlbmVkJGNvbnRlbnRfcGxheWVkIDwtIGlmZWxzZShzdHJfZGV0ZWN0KGNvbnRlbnRfbGlzdGVuZWQkbG9nSW5mbywgJ0NPTlRFTlQgUExBWUVEJywgbmVnYXRlID0gRkFMU0UpLDEsMCkKY29udGVudF9saXN0ZW5lZCRyZXBsYXlfcmVxdWVzdCA8LSBpZmVsc2Uoc3RyX2RldGVjdChjb250ZW50X2xpc3RlbmVkJGxvZ0luZm8sICdDT05URU5UIFJFUExBWSBSRVFVRVNURUQnLCBuZWdhdGUgPSBGQUxTRSksMSwwKQoKY29udGVudF9wbGF5ZWQ8LWFnZ3JlZ2F0ZShjb250ZW50X2xpc3RlbmVkJGNvbnRlbnRfcGxheWVkLGxpc3QoY29udGVudF9saXN0ZW5lZCRjYWxsZXJJZCksIEZVTj1zdW0pCj9yZW5hbWUKY29udGVudF9wbGF5ZWQgPC0gY29udGVudF9wbGF5ZWQgJT4lIAogIGRwbHlyOjpyZW5hbWUoCiAgICBjb25fcGxheSA9IHgsCiAgICBjYWxsZXJJZCA9IEdyb3VwLjEKICAgICkKCmNvbnRlbnRfcmVwbGF5PC1hZ2dyZWdhdGUoY29udGVudF9saXN0ZW5lZCRyZXBsYXlfcmVxdWVzdCxsaXN0KGNvbnRlbnRfbGlzdGVuZWQkY2FsbGVySWQpLCBGVU49c3VtKQpjb250ZW50X3JlcGxheSA8LSBjb250ZW50X3JlcGxheSAlPiUgCiBkcGx5cjo6cmVuYW1lKAogICAgY29uX3JlcGxheSA9IHgsCiAgICBjYWxsZXJJZCA9IEdyb3VwLjEKICAgICkKCmNvbnRlbnRfY291bnRzIDwtIGNiaW5kKGNvbnRlbnRfcGxheWVkLCBjb250ZW50X3JlcGxheSkKCmNvbnRlbnRfY291bnRzJGFkanVzdGVkX2NvbiA8LSBjb250ZW50X2NvdW50cyRjb25fcGxheS1jb250ZW50X2NvdW50cyRjb25fcmVwbGF5Cgpjb250ZW50X2NvdW50cyRjYWxsZXJJZCA8LSBOVUxMCgpzdW1tYXJ5KGNvbnRlbnRfY291bnRzJGFkanVzdGVkX2NvbikKCgojZ3JhcGhpbmcgdGhlIHRydWUgZGlzdHJpYnV0aW9uIG9mIGNvbnRlbnQgcGxheWVkCmdncGxvdChjb250ZW50X2NvdW50cywgYWVzKHg9YWRqdXN0ZWRfY29uKSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG9yPSJibGFjayIsIGZpbGw9ImdyZWVuIikgKwogIHhsaW0oMCwxMDApICsKICBsYWJzKAogICAgdGl0bGUgPSAnRGlzdHJpYnV0aW9uIG9mIHRvdGFsIENvbnRlbnQgbGlzdGVuZWQgdG8gYWxsIEFjcm9zcyBhbGwgQ2FsbHMgKE91dGxpZXJzIEV4Y2x1ZGVkKSBcbgogICAgICBNaW4uIDFzdCBRdS4gIE1lZGlhbiAgICBNZWFuIDNyZCBRdS4gICAgTWF4LiAKICAgMC4wMCAgICAzLjAwICAgIDguMDAgICAxNy43OSAgIDIwLjAwICAyNzkuMDAgJywKICAgIHggPSAnVG90YWwgQ29udGVudCBMaXN0ZW4gQWNyb3NzIENhbGxzJwogICkKCgojIEdldHRpbmcgdGhlIG51bWJlciBvZiBjYWxscyBwZXIgcGVyc29uCmNhbGxzX21hZGUgPC0gbG9nX2RhdGEgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGNhbGxJZCkgJT4lCiAgY291bnQoKQoKY2FsbHNfbWFkZV9pZCA8LSBsb2dfZGF0YSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY2FsbElkLCBjYWxsZXJJZCkgJT4lCiAgY291bnQoKQoKCiNqb2luIGJldHdlZW4gdGFibGVzCmNvbnRlbnRfcmF0aW8gPC0gbGVmdF9qb2luKGNhbGxzX21hZGVfaWQsIGNvbnRlbnRfY291bnRzLGJ5PSJjYWxsZXJJZCIpCmNvbnRlbnRfcmF0aW9baXMubmEoY29udGVudF9yYXRpbyldIDwtIDAKCmNvbnRlbnRfcmF0aW8gPC0gY29udGVudF9yYXRpbyAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY2FsbGVySWQsIGNvbl9wbGF5LCBjb25fcmVwbGF5LCBhZGp1c3RlZF9jb24pICU+JQogIGNvdW50KCkKCmNvbnRlbnRfcmF0aW8kcmF0aW8gPC0gY29udGVudF9yYXRpbyRhZGp1c3RlZF9jb24vY29udGVudF9yYXRpbyRuCgpzdW1tYXJ5KGNvbnRlbnRfcmF0aW8kcmF0aW8pCgpnZ3Bsb3QoY29udGVudF9yYXRpbywgYWVzKHg9cmF0aW8pKSArCiAgZ2VvbV9oaXN0b2dyYW0oY29sb3I9ImJsYWNrIiwgZmlsbD0icmVkIikgKwogIHhsaW0oMCwyKSsKICBsYWJzKAogICAgdGl0bGUgPSAnRGlzdHJpYnV0aW9uIG9mIHJhdGlvIG9mIGNvbnRlbnQgbGlzdGVuZWQgdG8gQ2FsbHMgKE91dGxpZXJzIEV4Y2x1ZGVkKSBcbgpNaW4uIDFzdCBRdS4gIE1lZGlhbiAgICBNZWFuIDNyZCBRdS4gICAgTWF4LiAgICAgCiAwLjAwMDAgIDAuNTYxNCAgMS4wMDAwICAxLjI1MDAgIDEuNTI5MiAxMy40MDAwICcsCiAgICB4ID0gJ0NvbnRlbnQgdG8gQ2FsbCBSYXRpbycKICApCgoKc3VtKGNvbnRlbnRfcmF0aW8kbikKYGBgCgojIyMgVE9QIE1FTlUKCioqTmV4dCwgd2Ugd2FudCB0byBCcmVha2QgZG93biB0aGUgaW5pdGlhbCBNZW51IG9wdGlvbnMgYW5kIGRlbHZlIGludG8gdGhlIGRpc3RyaWJ1dGlvbnMgb2YgdGhlIHNlbGVjdGlvbnMgdGhhdCB0aGUgZmFybWVyIGNhbiBtYWtlIGF0IGEgZGlmZmVyZW50IHN0YXRlIGluIHRoZSBJVlIgU3lzdGVtKioKCioqRm9yIHRoZSBmaXJzdCBhbmFseXNpcywgd2UgbG9va2VkIGF0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIFRPUCBNRU5VIGluIHRoZSBkYXRhLiBUaGlzIGNvbWVzIGluIGFzIGZvbGxvd3MqKjoKCiMjIyMjIElOQ09NSU5HIENBTEwgU1RBUlRFRCAtLT4gV0VMQ09NRSBNRVNTQUdFIFBMQVlFRCAtLT4gQVNTSU5HRUQgVE8gRVhQRVJJTUVOVCAoT1BUSU9OQUwpIC0tPiBUT1AgTUVOVQoKKipUT1AgTUVOVSoqCgogLSBSQUlOIE9QVElPTgogLSBISEkgT1BUSU9OIChob3VzZWhvbGQgSXJyaWdhdGlvbikKIC0gUkVTRVQgUFJPRklMRSBPUFRJT04KIC0gVE9QIE1FTlUgUkVQTEFZCiAtIExJVkVTVE9DSyBPUFRJT04gCiAtIENPVklEIE9QVElPTgogCiAqUGxlYXNlIG5vdGUsIHdlIGFyZSB1bnN1cmUgb2YgdGhlIG9yZGVyIHRoZXNlIGFyZSBwcmVzZW50ZWQuIEZvciBvdGhlciBtZW51cywgd2UgZG8gaGF2ZSB0aGUgb3JkZXIqCiAKICoqQmVsb3csIHdlIGhhdmUgdmlzdWFsaXplZCB0aGUgbnVtYmVyIG9mIGZhcm1lcnMsIG91dCBvZiBvdXIgc2FtcGxlLCB0aGF0IGluIHRoZSBsaWZlIHRpbWUgb2YgdGhlaXIgY2FsbGluZyBoaXN0b3J5IGhhdmUgYWNjZXNzZWQgYSBnaXZlbiBUT1AgTUVOVSBpdGVtIGF0IGxlYXN0IG9uY2UqKgogCiAqKkFkZGl0aW9uYWxseSwgd2UgYWxzbyB2aXN1YWxpemVkIHRoaXMgc2FtZSBzZWxlY3Rpb24gZGl2aWRlZCBieSBsYW5ndWFnZSB0byBzZWUgaWYgdGhlIHBhdHRlcm5zIG9mIHNlbGVjaW9udCBhcmUgc2ltaWxhciBvciBkaWZmZXJlbnQgYWNyb3NzIGxhbmdhdWdlcyoqdgogCmBgYHtyfQojU1RBUlRJTkcgSEVSRSBJUyBGT1IgVU5JUVVFIENBTExFUlMKIyBmaWx0ZXJpbmcgb3V0IHRvcCBNZW51IGtleXMKCnRvcF9tZW51IDwtZmlsdGVyKGxvZ19kYXRhLCBncmVwbCgiVE9QIE1FTlUiLGxvZ0luZm8pKQoKI2NsZWFuaW5nIHRoZSBheGlzCnRvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZSh0b3BfbWVudSRsb2dJbmZvLCAiVE9QIE1FTlUgLSAiLCAiIikKdG9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHRvcF9tZW51JGxvZ0luZm8sICIgUFJFU1NFRCIsICIiKQp0b3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UodG9wX21lbnUkbG9nSW5mbywgIiBQUkVTU0VEIiwgIiIpCnRvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZSh0b3BfbWVudSRsb2dJbmZvLCAiIFNFTEVDVEVEIiwgIiIpCgp0b3BfbWVudSA8LSB0b3BfbWVudSAlPiUKICBncm91cF9ieShjYWxsZXJJZCwgbG9nSW5mbywgbGFuZ0lkKSAlPiUKICBjb3VudCgpCgoKZ2dwbG90KHRvcF9tZW51LCBhZXMobG9nSW5mbykpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwLCBoanVzdCA9MSkpKwogIGdlb21fYmFyKCkrCiAgbGFicygKICAgIHRpdGxlID0gJ0Rpc3RpcnV0aW9uIG9mIFRPUCBNRU5VIGl0ZW1zIHNlbGVjdGVkIGF0IGxlYXN0IG9uY2UgYnkgYSB1bmlxdWUgY2FsbGVyJywKICAgIHggPSAnVE9QIE1FTlUgb3B0aW9ucycKICApCgpnZ3Bsb3QodG9wX21lbnUsIGFlcyhsYW5nSWQsIGZpbGwgPSBsb2dJbmZvKSkgKwogIGdlb21fYmFyKCkrCiAgbGFicygKICAgIHRpdGxlID0gJ0Rpc3RpcnV0aW9uIG9mIExhbmd1YWdlcyBkaXZpZGVkIGJ5IFRPUCBNRU5VIG9wdGlvbgogICAgMSA9IEFtaGFyaWMsIDI9T3JvbWlmZmEsIDM9VGlncmlnbmEsIDQ9V29sYXlpdHRhLCBhbmQgNT1TaWRhbWlnbmEnLAogICAgeCA9ICdMYW5ndWFnZScKICApCgojU1RBUlRJTkcgSEVSRSBJUyBGT1IgVU5JUVVFIENBTExTCgp0b3BfbWVudV9jYWxsIDwtZmlsdGVyKGxvZ19kYXRhLCBncmVwbCgiVE9QIE1FTlUiLGxvZ0luZm8pKQoKI2NsZWFuaW5nIHRoZSBheGlzCnRvcF9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHRvcF9tZW51X2NhbGwkbG9nSW5mbywgIlRPUCBNRU5VIC0gIiwgIiIpCnRvcF9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHRvcF9tZW51X2NhbGwkbG9nSW5mbywgIiBQUkVTU0VEIiwgIiIpCnRvcF9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHRvcF9tZW51X2NhbGwkbG9nSW5mbywgIiBQUkVTU0VEIiwgIiIpCnRvcF9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHRvcF9tZW51X2NhbGwkbG9nSW5mbywgIiBTRUxFQ1RFRCIsICIiKQoKdG9wX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UodG9wX21lbnVfY2FsbCRsb2dJbmZvLCAiUkFJTiBPUFRJT04iLCAiMSAtIFJBSU4gT1BUSU9OIikKdG9wX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UodG9wX21lbnVfY2FsbCRsb2dJbmZvLCAiSEhJIE9QVElPTiIsICIyIC0gSEhJIE9QVElPTiIpCnRvcF9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHRvcF9tZW51X2NhbGwkbG9nSW5mbywgIkxJVkVTVE9DSyBPUFRJT04iLCAiMyAtIExJVkVTVE9DSyBPUFRJT04iKQp0b3BfbWVudV9jYWxsJGxvZ0luZm88LSBzdHJfcmVwbGFjZSh0b3BfbWVudV9jYWxsJGxvZ0luZm8sICJDT1ZJRCBPUFRJT04iLCAiNCAtIENPVklEIE9QVElPTiIpCnRvcF9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHRvcF9tZW51X2NhbGwkbG9nSW5mbywgIlJFU0VUIFBST0ZJTEUgT1BUSU9OIiwgIlxcKiAtIFJFU0VUIFBST0ZJTEUiKQp0b3BfbWVudV9jYWxsJGxvZ0luZm88LSBzdHJfcmVwbGFjZSh0b3BfbWVudV9jYWxsJGxvZ0luZm8sICJUT1AgTUVOVSBSRVBMQVlFRCIsICJcXCMgLSBUT1AgTUVOVSBSRVBMQVlFRCIpCgp0b3BfbWVudV9jYWxsIDwtIHRvcF9tZW51X2NhbGwgJT4lCiAgZ3JvdXBfYnkoY2FsbElkLCBsb2dJbmZvKSAlPiUKICBjb3VudCgpCgp0b3BfbWVudV9jYWxsPC0gdG9wX21lbnVfY2FsbFttYXRjaCh1bmlxdWUodG9wX21lbnVfY2FsbCRjYWxsSWQpLCB0b3BfbWVudV9jYWxsJGNhbGxJZCksXQoKZ2dwbG90KHRvcF9tZW51X2NhbGwsIGFlcyh4PWZjdF9pbmZyZXEobG9nSW5mbykpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNSwgaGp1c3QgPTEpKSsKICBnZW9tX2Jhcihjb2xvcj0nYmxhY2snLCBmaWxsPSdyZWQnKSsKICBnZW9tX3RleHQoc3RhdD0nY291bnQnLCBhZXMobGFiZWw9Li5jb3VudC4uKSwgdmp1c3Q9LTEpKwogIHlsaW0oMCw2NTAwKSsKICBsYWJzKAogICAgdGl0bGUgPSAnRGlzdGlydXRpb24gb2YgVG9wIE1lbnUgT3B0aW9ucyBTZWxlY3RlZCBwZXIgQ2FsbCB3aXRoIE51bWJlciBQcmVzc2VkIEluZGljYXRlZCcsCiAgICB4ID0gJ1RvcCBNZW51IE9wdGlvbnMnLAogICAgeT0nTnVtYmVyIG9mIENhbGxzJwogICkKdW5pcXVlKHRvcF9tZW51X2NhbGwkY2FsbElkKQpjbGFzcyhsb2dfZGF0YSkKYGBgCiAKIAogCioqQXMgd2UgY2FuIGVhc2lseSBzZWUsIHRoZSBSQUlOIG9wdGlvbnMgYW5kIHRoZSBISEkgb3B0aW9uIGRvbWluYXRlIHRoZSBjaG9pY2VzIGZyb20gdGhlIHRvcCBNZW51LiBTbywgd2UgZGVjaWRlZCB0byBkaXZlIGRlZXBlciBpbnRvIGVhY2ggb2YgdGhlc2UgbWVudXMgdG8gc2VlIGlmIHRoZXJlIGFyZSBhbnkgb3V0bGllciBzZWxlY3Rpb25zIHRoYXQgYXJlIGRlZXAgd2l0aGluIHRoZSBzeXN0ZW0uIEFkZGl0aW9uYWxseSwgdGhzIGRpc3RyaWJ1dGlvbiBhY3Jvc3MgbGFuZ3VhZ2VzIHNlZW1zIHRvIGJlIGZhaXJseSBjb25zaXN0ZW50IGF0IGZhY2UgdmFsdWUuIFdlIGNhbiBydW4gdGVzdHMgaW4gdGhlIGZ1dHVyZSwgYnV0IGZvciBFREEgdGhpcyB3aWxsIGJlIGFkZXF1YXRlLiBGb3IgMy80IGxhbmdhdWdlIG9wdGlvbnMgLSBoYXZpbmcgbW9yZSBkYXRhIHdvdWxkIGJlIGFwcHJlY2FpdGVkKioKCgojIyMgUkFJTiBNRU5VCgojIyMjIyBJTkNPTUlORyBDQUxMIFNUQVJURUQgLS0+IFdFTENPTUUgTUVTU0FHRSBQTEFZRUQgLS0+IFJBTkRPTSBFWFBFUklNRU5UIC0tPiBUT1AgTUVOVSAtLT4gUkFJTiBNRU5VCgoqKkhlcmUsIHdlIGxvb2sgYXQgdGhlIGJyZWFrZG93biBvZiBpbmRpdmlkdWFscyB3aG8gaGF2ZSBzZWxlY3RlZCBhIGdpdmVuIG9wdGlvbiBpbiB0aGUgcmFpbiBtZW51IGF0IGxlYXN0IG9uY2UuIEluIHRoZSBkYXRhLCBNQUlOIE1FTlUgPT0gUkFJTiBNRU5VLioqCgoKKipSQUlOIE1FTlUqKgoKIC0gUFJFIFBMQU5USU5HIE9QVElPTgogLSBQTEFOVElORyBPUFRJT04KIC0gQ1JPUCBQUk9URUNUSU9OIE9QVElPTgogLSBGRVJUSUxJWkdFUiBTSURFIERSRUVTU0lORwogLSBQT1NUIEhBUlZFU1QgQU5EIFBST0NFU1NJTkcKIC0gUkVQRUFUIFJBSU4gTUVOVQogLSBSRVRVUk4gVE8gVE9QIE1FTlUKIC0gSU5WQUxJRCBLRVkgUFJFU1NFRCAoQURESVRJT05BTCBPVVRDT01FKQoKCgpgYGB7cn0KIyBQdWxsaW5nIG91dCB0aGUgcmFpbiBNZW51IEJ5IENBTExMRVIKCiNSQUlOID09IEhISV9SQUlOCnJhaW5fbWVudSA8LSBmaWx0ZXIobG9nX2RhdGEsIGdyZXBsKCJNQUlOIE1FTlUgLSAiLGxvZ0luZm8pKQpyYWluX21lbnUgPC0gZmlsdGVyKHJhaW5fbWVudSwgIWdyZXBsKCJMSVZFU1RPQ0sgTUFJTiBNRU5VIixsb2dJbmZvKSkKcmFpbl9tZW51IDwtIGZpbHRlcihyYWluX21lbnUsICFncmVwbCgiSEhJIE1BSU4gTUVOVSIsbG9nSW5mbykpCnJhaW5fbWVudSA8LSBmaWx0ZXIocmFpbl9tZW51LCAhZ3JlcGwoIkNPVklELTE5IE1BSU4gTUVOVSIsbG9nSW5mbykpCgojZ3JvdXBpbmcgdGhlIG9ic2VydmF0aW9ucwpyYWluX21lbnUgPC1yYWluX21lbnUgJT4lCiAgZ3JvdXBfYnkoY2FsbGVySWQsIGxvZ0luZm8sIGxhbmdJZCkgJT4lCiAgY291bnQoKQoKcmFpbl9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShyYWluX21lbnUkbG9nSW5mbywgIk1BSU4gTUVOVSAtICIsICIiKQpyYWluX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fbWVudSRsb2dJbmZvLCAiIFNFTEVDVEVEIiwgIiIpCnJhaW5fbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9tZW51JGxvZ0luZm8sICIgUFJFU1NFRCIsICIiKQpyYWluX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fbWVudSRsb2dJbmZvLCAiIE9QVElPTiIsICIiKQoKI3Bsb3R0aW5nIHJhaW4gbWVudSBicmVha2Rvd24KZ2dwbG90KGRhdGE9cmFpbl9tZW51LCBhZXMoeD1sb2dJbmZvKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIGhqdXN0ID0xKSkrCiAgZ2VvbV9iYXIoZmlsbD0nYmx1ZScpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdCcmVha2Rvd24gZm9yIEluZGl2aWR1YWxzIEJ5IENvbnRlbnQgU2VsZWN0ZWQgYXQgbGVhc3QgT25jZSBmcm9tIHRoZSByYWluIG1lbnUnLAogICAgeCA9ICdDb250ZW50IFNlbGVjdGVkJywKICAgIHk9ICdjb3VudCcKICApCgoKCiNET0lORyBJVCBCWSBDQUxMISEhIQpyYWluX21lbnVfY2FsbCA8LSBmaWx0ZXIobG9nX2RhdGEsIGdyZXBsKCJNQUlOIE1FTlUgLSAiLGxvZ0luZm8pKQpyYWluX21lbnVfY2FsbCA8LSBmaWx0ZXIocmFpbl9tZW51X2NhbGwsICFncmVwbCgiTElWRVNUT0NLIE1BSU4gTUVOVSIsbG9nSW5mbykpCnJhaW5fbWVudV9jYWxsIDwtIGZpbHRlcihyYWluX21lbnVfY2FsbCwgIWdyZXBsKCJISEkgTUFJTiBNRU5VIixsb2dJbmZvKSkKcmFpbl9tZW51X2NhbGwgPC0gZmlsdGVyKHJhaW5fbWVudV9jYWxsLCAhZ3JlcGwoIkNPVklELTE5IE1BSU4gTUVOVSIsbG9nSW5mbykpCgojZ3JvdXBpbmcgdGhlIG9ic2VydmF0aW9ucwpyYWluX21lbnVfY2FsbDwtcmFpbl9tZW51X2NhbGwgJT4lCiAgZ3JvdXBfYnkoY2FsbElkLCBsb2dJbmZvLCkgJT4lCiAgY291bnQoKQoKcmFpbl9tZW51X2NhbGw8LSByYWluX21lbnVfY2FsbFttYXRjaCh1bmlxdWUocmFpbl9tZW51X2NhbGwkY2FsbElkKSwgcmFpbl9tZW51X2NhbGwkY2FsbElkKSxdCgpyYWluX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9tZW51X2NhbGwkbG9nSW5mbywgIk1BSU4gTUVOVSAtICIsICIiKQpyYWluX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9tZW51X2NhbGwkbG9nSW5mbywgIiBTRUxFQ1RFRCIsICIiKQpyYWluX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9tZW51X2NhbGwkbG9nSW5mbywgIiBQUkVTU0VEIiwgIiIpCnJhaW5fbWVudV9jYWxsJGxvZ0luZm88LSBzdHJfcmVwbGFjZShyYWluX21lbnVfY2FsbCRsb2dJbmZvLCAiIE9QVElPTiIsICIiKQoKCiNGSXhpbmcgdGhlIEhISSBtZW51IGFuZCBhZGRpbmcgbnVtYmVlcnMKcmFpbl9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fbWVudV9jYWxsJGxvZ0luZm8sICJQUkUgUExBTlRJTkciLCAiMSAtIFBSRVBMWk5USU5HIikKcmFpbl9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fbWVudV9jYWxsJGxvZ0luZm8sICJQTEFOVElORyIsICIyIC0gUExBTlRJTkciKQpyYWluX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9tZW51X2NhbGwkbG9nSW5mbywgIjEgLSBQUkVQTFpOVElORyIsICIxIC0gUFJFUExBTlRJTkciKQpyYWluX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9tZW51X2NhbGwkbG9nSW5mbywgIkNST1AgUFJPVEVDVElPTiIsICIzIC0gQ1JPUCBQUk9URUNUSU9OIikKcmFpbl9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fbWVudV9jYWxsJGxvZ0luZm8sICJGRVJUSUxJWkVSIFNJREUgRFJFU1NJTkciLCAiNCAtIEZFUlRJTElaRVIgRFJFU1NJTkciKQpyYWluX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9tZW51X2NhbGwkbG9nSW5mbywgIlBPU1QgSEFSVkVTVCBBTkQgUFJPQ0VTU0lORyIsICI1IC0gUE9TVCBIQVJWRVNUL1BST0NFU1NJTkciKQpyYWluX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9tZW51X2NhbGwkbG9nSW5mbywgIkdPIFRPIE1BSU4gTUVOVSIsICIqIC0gR08gVE8gTUFJTiBNRU5VIikKcmFpbl9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fbWVudV9jYWxsJGxvZ0luZm8sICJNQUlOIE1FTlUgUkVQTEFZRUQiLCAiIyAtIE1BSU4gTUVOVSBSRVBMQVlFRCIpCgojcGxvdHRpbmcgcmFpbiBtZW51IGJyZWFrZG93bgpnZ3Bsb3QoZGF0YT1yYWluX21lbnVfY2FsbCwgYWVzKHg9ZmN0X2luZnJlcShsb2dJbmZvKSkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI1LCBoanVzdCA9MSkpKwogIGdlb21fYmFyKGNvbG9yPSdibGFjaycsIGZpbGw9J2JsdWUnLHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoIDAuMykpKwogIGdlb21fdGV4dChzdGF0PSdjb3VudCcsIGFlcyhsYWJlbD0uLmNvdW50Li4pLCB2anVzdD0tMSkrCiAgeWxpbSgwLDMyNTApKwogIGxhYnMoCiAgICB0aXRsZSA9ICdEaXN0aXJ1dGlvbiBvZiBSYWluIE1lbnUgT3B0aW9ucyBTZWxlY3RlZCBwZXIgQ2FsbCcsCiAgICB4ID0gJ1JhaW4gTWVudSBPcHRpb25zJywKICAgIHk9J051bWJlciBvZiBDYWxscycKICApCgojR0VUVElORyBISEkgTUVOVSBQRVIgQ0FMTApISElfbWVudV9jYWxsIDwtIGZpbHRlcihsb2dfZGF0YSwgZ3JlcGwoIkhISSBNQUlOIE1FTlUgLSAiLGxvZ0luZm8pKQoKI2dyb3VwaW5nIHRoZSBvYnNlcnZhdGlvbnMKSEhJX21lbnVfY2FsbDwtSEhJX21lbnVfY2FsbCAlPiUKICBncm91cF9ieShjYWxsSWQsIGxvZ0luZm8sKSAlPiUKICBjb3VudCgpCgpISElfbWVudV9jYWxsPC0gSEhJX21lbnVfY2FsbFttYXRjaCh1bmlxdWUoSEhJX21lbnVfY2FsbCRjYWxsSWQpLCBISElfbWVudV9jYWxsJGNhbGxJZCksXQoKSEhJX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoSEhJX21lbnVfY2FsbCRsb2dJbmZvLCAiSEhJIE1BSU4gTUVOVSAtICIsICIiKQpISElfbWVudV9jYWxsJGxvZ0luZm88LSBzdHJfcmVwbGFjZShISElfbWVudV9jYWxsJGxvZ0luZm8sICIgU0VMRUNURUQiLCAiIikKSEhJX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoSEhJX21lbnVfY2FsbCRsb2dJbmZvLCAiIFBSRVNTRUQiLCAiIikKSEhJX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoSEhJX21lbnVfY2FsbCRsb2dJbmZvLCAiIE9QVElPTiIsICIiKQoKCiNGSXhpbmcgdGhlIEhISSBtZW51IGFuZCBhZGRpbmcgbnVtYmVlcnMKSEhJX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoSEhJX21lbnVfY2FsbCRsb2dJbmZvLCAiUFJFIFBMQU5USU5HIiwgIjEgLSBQUkVQTEFOVElORyIpCkhISV9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKEhISV9tZW51X2NhbGwkbG9nSW5mbywgIlBMQU5USU5HIEFORCBUUkFOU1BMQU5USU5HIiwgIjIgLSBQTEFOVElORy9UUkFOU1BMQU5USU5HIikKSEhJX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoSEhJX21lbnVfY2FsbCRsb2dJbmZvLCAiSEFSUk9XSU5HIEFORCBFQVJUSE5JTkciLCAiMyAtIEhBUlJPV0lORy9FQVJUSE5JTkciKQpISElfbWVudV9jYWxsJGxvZ0luZm88LSBzdHJfcmVwbGFjZShISElfbWVudV9jYWxsJGxvZ0luZm8sICJJUlJJR0FUSU5HIENST1BTIiwgIjQgLSBJUlJJR0FUSU5HIENST1BTIikKSEhJX21lbnVfY2FsbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoSEhJX21lbnVfY2FsbCRsb2dJbmZvLCAiUFJPVEVDVElORyBDUk9QUyIsICI1IC0gUFJPVEVDVElORyBDUk9QUyIpCkhISV9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKEhISV9tZW51X2NhbGwkbG9nSW5mbywgIkFQUExZSU5HIEZFUlRJTElaRVIiLCAiNiAtIEFQUExZSU5HIEZFUlRJTElaRVIiKQpISElfbWVudV9jYWxsJGxvZ0luZm88LSBzdHJfcmVwbGFjZShISElfbWVudV9jYWxsJGxvZ0luZm8sICJIQVJWRVNUSU5HIEFORCBQUk9DRVNTSU5HIiwgIjcgLSBIQVJWRVNUSU5HL1BST0NFU1NJTkciKQpISElfbWVudV9jYWxsJGxvZ0luZm88LSBzdHJfcmVwbGFjZShISElfbWVudV9jYWxsJGxvZ0luZm8sICJHTyBUTyBNQUlOIE1FTlUiLCAiKiAtIEdPIFRPIE1BSU4gTUVOVSIpCkhISV9tZW51X2NhbGwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKEhISV9tZW51X2NhbGwkbG9nSW5mbywgIkhISSBNQUlOIE1FTlUgUkVQTEFZRUQiLCAiIyAtIEhISSBNQUlOIE1FTlUgUkVQTEFZRUQiKQoKCiNwbG90dGluZyByYWluIG1lbnUgYnJlYWtkb3duCmdncGxvdChkYXRhPUhISV9tZW51X2NhbGwsIGFlcyh4PWZjdF9pbmZyZXEobG9nSW5mbykpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwgaGp1c3QgPTEpKSsKICBnZW9tX2Jhcihjb2xvcj0nYmxhY2snLCBmaWxsPSdncmVlbicscG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSggMC4zKSkrCiAgZ2VvbV90ZXh0KHN0YXQ9J2NvdW50JywgYWVzKGxhYmVsPS4uY291bnQuLiksIHZqdXN0PS0xKSsKICB5bGltKDAsMTMwMCkrCiAgbGFicygKICAgIHRpdGxlID0gJ0Rpc3RpcnV0aW9uIG9mIEhISSBNZW51IE9wdGlvbnMgU2VsZWN0ZWQgcGVyIENhbGwnLAogICAgeCA9ICdISEkgTWVudSBPcHRpb25zJywKICAgIHk9J051bWJlciBvZiBDYWxscycKICApCgpgYGAKCgoKKipXZSBjYW4gc2VlIHRoYXQgdGhlIHByZS1wbGFudGluZyBtZW51LCB3aGljaCBzdGlsbCBoYXMgb3ZlciA3NSUgb2YgdW5pcXVlIHVzZXJzIGFjY2Vzc3MgaXQgYXQgbGVhc3Qgb25jZSBleHBlcmVpbmNlcyBpbmNyZWRpYmx5IGhpZ2ggdXNhZ2UuIFNvLCB3ZSBub3cgZGl2ZSBpbnRvIHRoaXMgbWVudS4gV2Ugd2lsbCBicmVha2Rvd24gY29uZW50IHNlbGVjdGlvbiBieSBsYW5ndWFnZSBhbmQgb3ZlcmFsbCoqCgoKIyMjIFJBSU4gTUVOVS9QUkUgUExBTlRJTkcgTUVOVQoKIyMjIyMgSU5DT01JTkcgQ0FMTCBTVEFSVEVEIC0tPiBXRUxDT01FIE1FU1NBR0UgUExBWUVEIC0tPiBSQU5ET00gRVhQRVJJTUVOVCAtLT4gCiMjIyMjIFRPUCBNRU5VIC0tPiBSQUlOIE1FTlUgLS0+IFBSRSBQTEFOVElORyBNRU5VCgoqKlBsZWFzZSBub3RlLCB0aGUgcHJlIHBsYW50aW5nIG1lbnUgdW5kZXIgdGhlIHJhaW4gbWVudSBpcyByZWZlcnJlZCB0byBhcyBNRU5VIDEgaW4gdGhlIGRhdGEqKgoKCioqUFJFIFBMQU5USU5HIE1FTlUqKgoKIC0gTEFORCBQUkVQQVJBVElPTgogLSBTRUVEIFZBUklFVFkKIC0gUkVQRUFUIE1FTlUKIC0gR08gVE8gTUFJTiBNRU5VIChSQUlOIE1FTlUpCiAtIElOVkFMSUQgS0VZIChBRERJVElPTkFMIE9VVENPTUUpCiAKIApgYGB7cn0KCgojZmlsdGVyaW5nIG91dCBNRU5VIDEgb3B0aW9ucyBhcyB0aGUgcHJlIHBsYW50aW5nCk1FTlVfMSA8LSBmaWx0ZXIobG9nX2RhdGEsIGdyZXBsKCJNRU5VIDEiLGxvZ0luZm8pKQpNRU5VXzEgPC0gZmlsdGVyKE1FTlVfMSwgIWdyZXBsKCJISElNRU5VIDEiLGxvZ0luZm8pKQpNRU5VXzEgPC0gZmlsdGVyKE1FTlVfMSwgIWdyZXBsKCJBUElDVUxUVVJFIE1FTlUiLGxvZ0luZm8pKQpNRU5VXzEgPC0gZmlsdGVyKE1FTlVfMSwgIWdyZXBsKCJBUElDVUxUVVJFIFNVQjQgTUVOVSIsbG9nSW5mbykpCk1FTlVfMSA8LSBmaWx0ZXIoTUVOVV8xLCAhZ3JlcGwoIkRBSVJZIE1FTlUiLGxvZ0luZm8pKQpNRU5VXzEgPC0gZmlsdGVyKE1FTlVfMSwgIWdyZXBsKCJTTUFMTC1TQ0FMRSBTVUI1IE1FTlUiLGxvZ0luZm8pKQpNRU5VXzEgPC0gZmlsdGVyKE1FTlVfMSwgIWdyZXBsKCJEQUlSWSBTVUIyIE1FTlUiLGxvZ0luZm8pKQpNRU5VXzEgPC0gZmlsdGVyKE1FTlVfMSwgIWdyZXBsKCJGQVRURU5JTkcgTUFOVSIsbG9nSW5mbykpCgpNRU5VXzEgPC0gZmlsdGVyKE1FTlVfMSwgIWdyZXBsKCJGQVRURU5JTkcgU1VCMSBNRU5VIixsb2dJbmZvKSkKTUVOVV8xIDwtIGZpbHRlcihNRU5VXzEsICFncmVwbCgiRkFUVEVOSU5HIFNVQjIgTUVOVSIsbG9nSW5mbykpCk1FTlVfMSA8LSBmaWx0ZXIoTUVOVV8xLCAhZ3JlcGwoIkhPVVNFSE9MRCBNRU5VIixsb2dJbmZvKSkKTUVOVV8xIDwtIGZpbHRlcihNRU5VXzEsICFncmVwbCgiSE9VU0VIT0xEIFNVQjEgTUVOVSAiLGxvZ0luZm8pKQoKCk1FTlVfMSA8LSBNRU5VXzEgJT4lCiAgZ3JvdXBfYnkoY2FsbGVySWQsIGxvZ0luZm8sIGxhbmdJZCkgJT4lCiAgY291bnQoKQoKTUVOVV8xJGxvZ0luZm88LSBzdHJfcmVwbGFjZShNRU5VXzEkbG9nSW5mbywgIk1FTlUgMSAtICIsICIiKQpNRU5VXzEkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKE1FTlVfMSRsb2dJbmZvLCAiIFBSRVNTRUQiLCAiIikKTUVOVV8xJGxvZ0luZm88LSBzdHJfcmVwbGFjZShNRU5VXzEkbG9nSW5mbywgIiBTRUxFQ1RFRCIsICIiKQoKIyBwbG90dGluZwpnZ3Bsb3QoZGF0YT1NRU5VXzEsIGFlcyh4PWxvZ0luZm8pKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNSwgaGp1c3Q9IDEpKSsKICBnZW9tX2JhcihmaWxsPSdjeWFuJykrCiAgbGFicygKICAgIHRpdGxlID0gJ0luZGl2aWR1YWxzIEJ5IENvbnRlbnQgU2VsZWN0ZWQgYXQgbGVhc3QgT25jZSBmcm9tIAogICAgUkFJTiBNRU5VL1BSRSBQTEFOVElORyBPUFRJT04nLAogICAgeCA9ICdDb250ZW50IFNlbGVjdGVkJywKICAgIHk9ICdjb3VudCcKICApCgoKCmBgYAoKCiMjIyBSQUlOIE1FTlUvUFJFIFBMQU5USU5HIE1FTlUvTEFORCBQUkVQQVJBVElPTgoKCioqV2UgY29udGludWUgb3VyIHBhdHRlcm4gb2YgZm9sbG93aW5nIHRoZSBtb3N0IGFjY2Vzc2VkIHN1Ym1lbnUgZnJvbSB0aGUgcHJldmlvdXMgc3VibWVudCAtIGxhbmQgcHJlcGFyYXRpb24hIFRoaXMgaXMgYWxzbyB0aGUgYm90dG9tIG9mIGEgdHJlZS4gV2Ugd2lsbCBicmVha2Rvd24gY29uZW50IHNlbGVjdGlvbiBieSBsYW5ndWFnZSBhbmQgb3ZlcmFsbCoqCgoKIyMjIyMgSU5DT01JTkcgQ0FMTCBTVEFSVEVEIC0tPiBXRUxDT01FIE1FU1NBR0UgUExBWUVEIC0tPiBSQU5ET00gRVhQRVJJTUVOVCAtLT4gCiMjIyMjIFRPUCBNRU5VIC0tPiBSQUlOIE1FTlUgLS0+IFBSRSBQTEFOVElORyBNRU5VIC0tPiBMQU5EIFBSRVBBUkFUSU9OCgoqKkxBTkQgUFJFUEFSQVRJT04qKgoKIC0gQkFSTEVZCiAtIE1BSVpFCiAtIFNPUkdIVU0KIC0gVEVGCiAtIFdIRUFUCiAtIFNFU0FNRQogLSBGQVZBIEJFQU4KIC0gQ0hJQ0tQRUEKIC0gQ09NTU9OIEJFQU4KIC0gQ09UVE9OCgpPUkRFUiBVTktPV046CgogLSBSSUNFCiAtIERVUkFNRSBXSEVBVAogLSBMRU5USUwKIC0gTUFMVCBCQVJMRVkKIAogCmBgYHtyfQojR0VUVElORyBUSEUgQ1JPUCBNRU5VIEZST00gTUVOVSAxIChyYWluL3ByZXBsYW50aW5nL2xhbmQgcHJlcGFyYXRpb24gc3ViIG1lbnUpCmxhbmRfcHJlcCA8LSBmaWx0ZXIobG9nX2RhdGEsIGdyZXBsKCJDT05URU5UIFBMQVlFRCAtIExBTkQgUFJFUEFSQVRJT04gLSAiLGxvZ0luZm8pKQoKbGFuZF9wcmVwX2ZpbmFsIDwtIGxhbmRfcHJlcCAlPiUKICBncm91cF9ieShjYWxsZXJJZCwgbG9nSW5mbywgbGFuZ0lkKSAlPiUKICBjb3VudCgpCgpsYW5kX3ByZXBfZmluYWwkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGxhbmRfcHJlcF9maW5hbCRsb2dJbmZvLCAiQ09OVEVOVCBQTEFZRUQgLSBMQU5EIFBSRVBBUkFUSU9OIC0iLCAiIikKCmdncGxvdChkYXRhPWxhbmRfcHJlcF9maW5hbCwgYWVzKHg9bG9nSW5mbykpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0yKSkrCiAgZ2VvbV9iYXIoKSsKICBsYWJzKAogICAgdGl0bGUgPSAnUkFJTiBNRU5VL1BSRSBQTEFOVElORy9MQU5EIFBSRVBBUkFUSU9OCiAgICBjb250ZW50IGFjdHVhbGx5IHBsYXllZCBieSBsYW5ndWFnZScsCiAgICB4ID0gJ0NvbnRlbnQgUGxheWVkJywKICAgIHk9ICdjb3VudCcKICApCgoKI2dldCByaWQgb2YgdGhlIGxhbmd1YWdlIGJyZWFrZG93bgpsYW5kX3ByZXBfbm9fbGFuZyA8LSBsYW5kX3ByZXBfZmluYWwKCmxhbmRfcHJlcF9ub19sYW5nJGxvZ0luZm88LSBzdHJfcmVwbGFjZShsYW5kX3ByZXBfbm9fbGFuZyRsb2dJbmZvLCAiLSBBTUhBUklDIiwgIiIpCmxhbmRfcHJlcF9ub19sYW5nJGxvZ0luZm88LSBzdHJfcmVwbGFjZShsYW5kX3ByZXBfbm9fbGFuZyRsb2dJbmZvLCAiLSBPUk9NSUZGQSIsICIiKQpsYW5kX3ByZXBfbm9fbGFuZyRsb2dJbmZvPC0gc3RyX3JlcGxhY2UobGFuZF9wcmVwX25vX2xhbmckbG9nSW5mbywgIi0gVElHUklHTkEiLCAiIikKbGFuZF9wcmVwX25vX2xhbmckbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGxhbmRfcHJlcF9ub19sYW5nJGxvZ0luZm8sICItIFdPTEFZSVRUQSIsICIiKQpsYW5kX3ByZXBfbm9fbGFuZyRsb2dJbmZvPC0gc3RyX3JlcGxhY2UobGFuZF9wcmVwX25vX2xhbmckbG9nSW5mbywgIi0gV09MQVlUSUdOQSIsICIiKQpsYW5kX3ByZXBfbm9fbGFuZyRsb2dJbmZvPC0gc3RyX3JlcGxhY2UobGFuZF9wcmVwX25vX2xhbmckbG9nSW5mbywgIi0gU0lEQU1JR05BIiwgIiIpCgpnZ3Bsb3QobGFuZF9wcmVwX25vX2xhbmcsIGFlcyh4PWxvZ0luZm8pKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpKwogIGdlb21fYmFyKCkrCiAgbGFicygKICAgIHRpdGxlID0gJ1JBSU4gTUVOVS9QUkUgUExBTlRJTkcvTEFORCBQUkVQQVJBVElPTgogICAgY29udGVudCBwbGF5ZWQgb3ZlcmFsbCcsCiAgICB4ID0gJ0NvbnRlbnQgUGxheWVkJywKICAgIHk9ICdjb3VudCcKICApCgpnZ3Bsb3QobGFuZF9wcmVwX25vX2xhbmcsIGFlcyhsYW5nSWQsIGZpbGwgPSBsb2dJbmZvKSkgKwogIGdlb21fYmFyKCkrCiAgbGFicygKICAgIHRpdGxlID0gJ0FMVEVSTkFUSVZFIFJBSU4gTUVOVS9QUkUgUExBTlRJTkcvTEFORCBQUkVQQVJBVElPTgogICAgY29udGVudCBhY3R1YWxseSBwbGF5ZWQgYnkgbGFuZ3VhZ2UKICAgIDEgPSBBbWhhcmljLCAyPU9yb21pZmZhLCAzPVRpZ3JpZ25hLCA0PVdvbGF5aXR0YSwgYW5kIDU9U2lkYW1pZ25hCiAgICAnLAogICAgeCA9ICdMYW5ndWFnZScKICApCmBgYAogCgoqKkJJRyBUQUtFQVdBWTogMzUlIG9mIHVzZXJzIGVuZCB1cCBhY2Nlc3NpbmcgdGhlIG1haXplIG1lbnUgYXQgc29tZSBwb2ludCEgV2hlYXQsIFRlZiwgU29yZ2h1bSwgYW5kIEJhcmxleSBhbHNvIGFwcGVhciB0byBiZSBxdWFsaXRhdGl2ZWx5IHNpZ25pZmljYW50KioKCioqVGhlcmUgaXMgbm8gbWVudSB0byBnbyBkZWVwZXIgaW4sIHNvIGxldCdzIGdvIGJhY2sgdXAgYSBsZXZlbCBhbmQgY2hlY2sgdG8gc2VlIGlmIG90aGVyIGJyYW5jaGVzIGhhdmUgYSBsb3Qgb2YgYWNjZXNzKioKCgojIyMgUkFJTiBNRU5VL1BSRSBQTEFOVElORyBNRU5VL1NFRUQgVkFSSUVUWQoKCiMjIyMjIElOQ09NSU5HIENBTEwgU1RBUlRFRCAtLT4gV0VMQ09NRSBNRVNTQUdFIFBMQVlFRCAtLT4gUkFORE9NIEVYUEVSSU1FTlQgLS0+IAojIyMjIyBUT1AgTUVOVSAtLT4gUkFJTiBNRU5VIC0tPiBQUkUgUExBTlRJTkcgTUVOVSAtLT4gU0VFRCBWQVJJRVRZCgoqKlNFRUQgVkFSSUVUWSoqCgogLSBCQVJMRVkKIC0gTUFJWkUKIC0gU09SR0hVTQogLSBURUYKIC0gV0hFQVQKIC0gU0VTQU1FCiAtIEZBVkEgQkVBTgogLSBDSElDS1BFQQogLSBDT01NT04gQkVBTgoKYGBge3J9CiNHRVRUSU5HIFRIRSBDUk9QIE1FTlUgRlJPTSBNRU5VIDEgKHJhaW4vcHJlcGxhbnRpbmcvc2VlZCB2YXJpZXR5IHN1YiBtZW51KQpzZWVkX3ZhcmlldHkgPC0gZmlsdGVyKGxvZ19kYXRhLCBncmVwbCgiQ09OVEVOVCBQTEFZRUQgLSBTRUVEIFZBUklUWSIsbG9nSW5mbykpCgpzZWVkX3ZhcmlldHlfZmluYWwgPC0gc2VlZF92YXJpZXR5ICU+JQogIGdyb3VwX2J5KGNhbGxlcklkLCBsb2dJbmZvLCBsYW5nSWQpICU+JQogIGNvdW50KCkKCnNlZWRfdmFyaWV0eV9maW5hbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2Uoc2VlZF92YXJpZXR5X2ZpbmFsJGxvZ0luZm8sICJDT05URU5UIFBMQVlFRCAtIFNFRUQgVkFSSVRZIC0gIiwgIiIpCgpnZ3Bsb3QoZGF0YT1zZWVkX3ZhcmlldHlfZmluYWwsIGFlcyh4PWxvZ0luZm8pKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3Q9MSkpKwogIGdlb21fYmFyKCkrCiAgbGFicygKICAgIHRpdGxlID0gJ1JBSU4gTUVOVS9QUkUgUExBTlRJTkcvU0VFRCBWQVJJRVRZCiAgICBjb250ZW50IGFjdHVhbGx5IHBsYXllZCBieSBsYW5ndWFnZScsCiAgICB4ID0gJ0NvbnRlbnQgU2VsZWN0ZWQnLAogICAgeT0gJ2NvdW50JwogICkKCgojZ2V0IHJpZCBvZiB0aGUgbGFuZ3VhZ2UgYnJlYWtkb3duCnNlZWRfdmFyaWV0eV9ub19sYW5nIDwtIHNlZWRfdmFyaWV0eV9maW5hbAoKc2VlZF92YXJpZXR5X25vX2xhbmckbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHNlZWRfdmFyaWV0eV9ub19sYW5nJGxvZ0luZm8sICItIEFNSEFSSUMiLCAiIikKc2VlZF92YXJpZXR5X25vX2xhbmckbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHNlZWRfdmFyaWV0eV9ub19sYW5nJGxvZ0luZm8sICItIE9ST01JRkZBIiwgIiIpCnNlZWRfdmFyaWV0eV9ub19sYW5nJGxvZ0luZm88LSBzdHJfcmVwbGFjZShzZWVkX3ZhcmlldHlfbm9fbGFuZyRsb2dJbmZvLCAiLSBUSUdSSUdOQSIsICIiKQpzZWVkX3ZhcmlldHlfbm9fbGFuZyRsb2dJbmZvPC0gc3RyX3JlcGxhY2Uoc2VlZF92YXJpZXR5X25vX2xhbmckbG9nSW5mbywgIi0gV09MQVlJVFRBIiwgIiIpCnNlZWRfdmFyaWV0eV9ub19sYW5nJGxvZ0luZm88LSBzdHJfcmVwbGFjZShzZWVkX3ZhcmlldHlfbm9fbGFuZyRsb2dJbmZvLCAiLSBXT0xBWVRJR05BIiwgIiIpCnNlZWRfdmFyaWV0eV9ub19sYW5nJGxvZ0luZm88LSBzdHJfcmVwbGFjZShzZWVkX3ZhcmlldHlfbm9fbGFuZyRsb2dJbmZvLCAiLSBTSURBTUlHTkEiLCAiIikKCiNhbHRlcm5hdGl2ZSB3aXRoIGxhbmdhdWdlIHZpZXcKZ2dwbG90KHNlZWRfdmFyaWV0eV9ub19sYW5nLCBhZXMobGFuZ0lkLCBmaWxsID0gbG9nSW5mbykpICsKICBnZW9tX2JhcigpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdBTFRFUk5BVElWRSBSQUlOIE1FTlUvUFJFIFBMQU5USU5HL1NFRSBWQVJJRVRZCiAgICBjb250ZW50IGFjdHVhbGx5IHBsYXllZCBieSBsYW5ndWFnZQogICAgMSA9IEFtaGFyaWMsIDI9T3JvbWlmZmEsIDM9VGlncmlnbmEsIDQ9V29sYXlpdHRhLCBhbmQgNT1TaWRhbWlnbmEKICAgICcsCiAgICB4ID0gJ0xhbmd1YWdlJwogICkKCiNubyBsYW5ndWFnZSAtIG92ZXJhbGwKZ2dwbG90KHNlZWRfdmFyaWV0eV9ub19sYW5nLCBhZXMoeD1sb2dJbmZvKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIGhqdXN0PTEpKSsKICBnZW9tX2JhcigpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdSQUlOIE1FTlUvUFJFIFBMQU5USU5HL3NlZWQgdmFyaWV0eQogICAgY29udGVudCBhY3R1YWxseSBwbGF5ZWQnLAogICAgeCA9ICdDb250ZW50IFNlbGVjdGVkJywKICAgIHk9ICdjb3VudCcKICApCgoKYGBgCiAKKipXZSBoYXZlIG1vc3RseSBleGhhdXN0ZWQgdGhlIHByZS1wbGFudGluZyBvcHRpb24gbWVudSwgYW5kIGlmIHdlIGdvIGJhY2sgdXAgdG8gdGhlIG9yaWdpbmFsIHJhaW4gbWVudSAoYWthIE1BSU4gTUVOVSksIHdlIGNhbiBzZWUgdGhhdCBwbGFudGluZyBhbHNvIGhhcyBhIGxhcmdlIHBvcnBvcnRpb24gb2YgdXNlcnMgLSBvdmVyIGhhbGYqKgoKCiMjIyBSQUlOIE1FTlUvUExBTlRJTkcgTUVOVQoKCiMjIyMjIElOQ09NSU5HIENBTEwgU1RBUlRFRCAtLT4gV0VMQ09NRSBNRVNTQUdFIFBMQVlFRCAtLT4gUkFORE9NIEVYUEVSSU1FTlQgLS0+IAojIyMjIyBUT1AgTUVOVSAtLT4gUkFJTiBNRU5VIC0tPiBQTEFOVElORyBNRU5VCgoqKlRoZSBwbGFudGluZyBvcHRpb24gYXMgYSBzdWJzZWN0aW9uIG9mIHRoZSByYWluIG9wdGlvbiBpcyBrbm93biBhcyBNRU5VIDIgaW4gdGhlIGRhdGEqKgoKUExBTlRJTkcgTUVOVQoKIC0gU0VFRCBSQVRFCiAtIFNPSUwgREVQVEggUExBTlRJTkcKIC0gVFJBTlNQTEFOVElORwogLSBNT0lTVFVSRSBDT05TRVJWQVRJT04KIC0gRkVSVElMSVpFUiBBUFBMSUNBVElPTgogLSBSRVBMQVkgTUVOWQogLSBSRVRVUk4gVE8gUkFJTiBNRU5ZCiAtIElOVkFMSUQgS0VZIChBRERJVElPTkFMIE9VVENPTUUpCiAKCgpgYGB7cn0KI1BMQU5USU5HIE9QVElPTiAtIHNlY29uZCBtb3N0IGFjY2Vzc2VkIE1FTlUgMgpNRU5VXzIgPC0gZmlsdGVyKGxvZ19kYXRhLCBncmVwbCgiTUVOVSAyIixsb2dJbmZvKSkKTUVOVV8yIDwtIGZpbHRlcihNRU5VXzIsICFncmVwbCgiSEhJTUVOVSAyIixsb2dJbmZvKSkKTUVOVV8yIDwtIGZpbHRlcihNRU5VXzIsICFncmVwbCgiQVBJQ1VMVFVSRSBNRU5VIixsb2dJbmZvKSkKTUVOVV8yIDwtIGZpbHRlcihNRU5VXzIsICFncmVwbCgiQVBJQ1VMVFVSRSBTVUIyIE1FTlUiLGxvZ0luZm8pKQpNRU5VXzIgPC0gZmlsdGVyKE1FTlVfMiwgIWdyZXBsKCJEQUlSWSBNRU5VIixsb2dJbmZvKSkKTUVOVV8yIDwtIGZpbHRlcihNRU5VXzIsICFncmVwbCgiRkFUVEVOSU5HIE1BTlUiLGxvZ0luZm8pKQoKTUVOVV8yIDwtIE1FTlVfMiAlPiUKICBncm91cF9ieShjYWxsZXJJZCwgbG9nSW5mbywgbGFuZ0lkKSAlPiUKICBjb3VudCgpCgojY2xlYW5pbmcKTUVOVV8yJGxvZ0luZm88LSBzdHJfcmVwbGFjZShNRU5VXzIkbG9nSW5mbywgIk1FTlUgMiAtICIsICIiKQpNRU5VXzIkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKE1FTlVfMiRsb2dJbmZvLCAiIFNFTEVDVEVEIiwgIiIpCk1FTlVfMiRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoTUVOVV8yJGxvZ0luZm8sICIgUFJFU1NFRCIsICIiKQpNRU5VXzIkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKE1FTlVfMiRsb2dJbmZvLCAiIE9QVElPTiIsICIiKQoKCiNwbG90dGluZwpnZ3Bsb3QoZGF0YT1NRU5VXzIsIGFlcyh4PWZjdF9pbmZyZXEobG9nSW5mbykpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3Q9MSkpKwogIGdlb21fYmFyKGZpbGw9J29saXZlZHJhYicpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdJbmRpdmlkdWFscyBCeSBDb250ZW50IFNlbGVjdGVkIGF0IGxlYXN0IE9uY2UgZnJvbSAKICAgIFJBSU4gTUVOVS9QTEFOVElORyBPUFRJT04nLAogICAgeCA9ICdDb250ZW50IFNlbGVjdGVkJywKICAgIHk9ICdjb3VudCcKICApCmBgYAoKCgoqKkFzIHBlciB1c3VhbCwgd2Ugd2lsbCBnbyBpbnRvIHRoZSBtb3N0IGNvbW1vbiBzZWxlY3Rpb246IHNlZWQgcmF0ZSEqKgoKIyMjIFJBSU4gTUVOVS9QTEFOVElORyBNRU5VL1NFRUQgUkFURQoKCiMjIyMjIElOQ09NSU5HIENBTEwgU1RBUlRFRCAtLT4gV0VMQ09NRSBNRVNTQUdFIFBMQVlFRCAtLT4gUkFORE9NIEVYUEVSSU1FTlQgLS0+IAojIyMjIyBUT1AgTUVOVSAtLT4gUkFJTiBNRU5VIC0tPiBQTEFOVElORyBNRU5VIC0tPiBTRUVEIFJBVEUKCgoqKlNFRUQgUkFURSoqCgogLSBCQVJMRVkKIC0gTUFJWkUKIC0gU09SR0hVTQogLSBURUYKIC0gV0hFQVQKIC0gU0VTQU1FCiAtIEZBVkEgQkVBTgogLSBDSElDS1BFQQogLSBDT01NT04gQkVBTgogLSBDT1RUT04KCk9SREVSIFVOS09XTjoKCiAtIFJJQ0UKIC0gRFVSQU1FIFdIRUFUCiAtIExFTlRJTAogLSBNQUxUIEJBUkxFWQoKYGBge3J9CnNlZWRfcmF0ZSA8LSBmaWx0ZXIobG9nX2RhdGEsIGdyZXBsKCJDT05URU5UIFBMQVlFRCAtIFNFRUQgUkFURSIsbG9nSW5mbykpCgpzZWVkX3JhdGVfZmluYWwgPC0gc2VlZF9yYXRlICU+JQogIGdyb3VwX2J5KGNhbGxlcklkLCBsb2dJbmZvLCBsYW5nSWQpICU+JQogIGNvdW50KCkKCnNlZWRfcmF0ZV9maW5hbCRsb2dJbmZvPC0gc3RyX3JlcGxhY2Uoc2VlZF9yYXRlX2ZpbmFsJGxvZ0luZm8sICJDT05URU5UIFBMQVlFRCAtIFNFRUQgUkFURSAtIiwgIiIpCgpnZ3Bsb3QoZGF0YT1zZWVkX3JhdGVfZmluYWwsIGFlcyh4PWxvZ0luZm8pKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSxoanVzdD0xKSkrCiAgZ2VvbV9iYXIoKSsKICBsYWJzKAogICAgdGl0bGUgPSAnUkFJTiBNRU5VL1BMQU5USU5HL1NFRUQgUkFURQogICAgY29udGVudCBhY3R1YWxseSBwbGF5ZWQgYnkgbGFuZ3VhZ2UnLAogICAgeCA9ICdDb250ZW50IFNlbGVjdGVkJywKICAgIHk9ICdjb3VudCcKICApCgojZ2V0IHJpZCBvZiB0aGUgbGFuZ3VhZ2UgYnJlYWtkb3duCnNlZWRfcmF0ZV9ub19sYW5nIDwtIHNlZWRfcmF0ZV9maW5hbAoKc2VlZF9yYXRlX25vX2xhbmckbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHNlZWRfcmF0ZV9ub19sYW5nJGxvZ0luZm8sICItIEFNSEFSSUMiLCAiIikKc2VlZF9yYXRlX25vX2xhbmckbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHNlZWRfcmF0ZV9ub19sYW5nJGxvZ0luZm8sICItIE9ST01JRkZBIiwgIiIpCnNlZWRfcmF0ZV9ub19sYW5nJGxvZ0luZm88LSBzdHJfcmVwbGFjZShzZWVkX3JhdGVfbm9fbGFuZyRsb2dJbmZvLCAiLSBUSUdSSUdOQSIsICIiKQpzZWVkX3JhdGVfbm9fbGFuZyRsb2dJbmZvPC0gc3RyX3JlcGxhY2Uoc2VlZF9yYXRlX25vX2xhbmckbG9nSW5mbywgIi0gV09MQVlJVFRBIiwgIiIpCnNlZWRfcmF0ZV9ub19sYW5nJGxvZ0luZm88LSBzdHJfcmVwbGFjZShzZWVkX3JhdGVfbm9fbGFuZyRsb2dJbmZvLCAiLSBXT0xBWVRJR05BIiwgIiIpCnNlZWRfcmF0ZV9ub19sYW5nJGxvZ0luZm88LSBzdHJfcmVwbGFjZShzZWVkX3JhdGVfbm9fbGFuZyRsb2dJbmZvLCAiLSBTSURBTUlHTkEiLCAiIikKCiNhbHRlcm5hdGl2ZSB3aXRoIGxhbmdhdWdlIHZpZXcKZ2dwbG90KHNlZWRfcmF0ZV9ub19sYW5nLCBhZXMobGFuZ0lkLCBmaWxsID0gbG9nSW5mbykpICsKICBnZW9tX2JhcigpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdBTFRFUk5BVElWRSBSQUlOIE1FTlUvUExBTlRJTkcvU0VFRCBSQVRFCiAgICBjb250ZW50IGFjdHVhbGx5IHBsYXllZCBieSBsYW5ndWFnZQogICAgMSA9IEFtaGFyaWMsIDI9T3JvbWlmZmEsIDM9VGlncmlnbmEsIDQ9V29sYXlpdHRhLCBhbmQgNT1TaWRhbWlnbmEKICAgICcsCiAgICB4ID0gJ0xhbmd1YWdlJwogICkKI25vIGxhbmd1YWdlCmdncGxvdChzZWVkX3JhdGVfbm9fbGFuZywgYWVzKHg9bG9nSW5mbykpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xKSkrCiAgZ2VvbV9iYXIoKSsKICBsYWJzKAogICAgdGl0bGUgPSAnUkFJTiBNRU5VL1BMQU5USU5HL1NFRUQgUkFURQogICAgY29udGVudCBhY3R1YWxseSBwbGF5ZWQnLAogICAgeCA9ICdDb250ZW50IFNlbGVjdGVkJywKICAgIHk9ICdjb3VudCcKICApCgpgYGAKCgoKCmBgYHtyfQpjcm9wX21lbnUgPC0gbG9nX2RhdGEgJT4lCiAgZmlsdGVyKGdyZXBsKCJDUk9QIE1FTlUgLSAiLGxvZ0luZm8pKSAlPiUKICBmaWx0ZXIoIWdyZXBsKCJISEkiLGxvZ0luZm8pKSAlPiUKICBmaWx0ZXIoIWdyZXBsKCJSRVBMQVlFRCIsbG9nSW5mbykpCgpjcm9wX21lbnUgPC0gY3JvcF9tZW51ICU+JQogIGdyb3VwX2J5KGNhbGxlcklkLCBsb2dJbmZvLCBsYW5nSWQpICU+JQogIGNvdW50KCkKCmNyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY3JvcF9tZW51JGxvZ0luZm8sICJDUk9QIE1FTlUgLSAiLCAiIikKY3JvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShjcm9wX21lbnUkbG9nSW5mbywgIiBTRUxFQ1RFRCIsICIiKQpjcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNyb3BfbWVudSRsb2dJbmZvLCAiR08gVE8iLCAiIikKCgpnZ3Bsb3QoY3JvcF9tZW51LCBhZXMoeD1sb2dJbmZvKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0ID0xLCBzaXplID0gNykpKwogIGdlb21fYmFyKCkrCiAgbGFicygKICAgIHRpdGxlID0gJ0Nyb3AgbWVudSBicmVha2Rvd24nLAogICAgeCA9ICdDcm9wcycsCiAgICB5PSAnY291bnQnCiAgKQoKZ2dwbG90KGNyb3BfbWVudSwgYWVzKGxhbmdJZCwgZmlsbCA9IGxvZ0luZm8pKSArCiAgZ2VvbV9iYXIoKSsKICBsYWJzKAogICAgdGl0bGUgPSAnQ1JPUCBNRU5VIEJZIExBTkdVQUdFCiAgICAxID0gQW1oYXJpYywgMj1Pcm9taWZmYSwgMz1UaWdyaWduYSwgND1Xb2xheWl0dGEsIGFuZCA1PVNpZGFtaWduYQogICAgJywKICAgIHggPSAnTGFuZ3VhZ2UnCiAgKQpudW1fY3JvcF90eXBlcyA8LSBkYXRhLmZyYW1lKGFzLm51bWVyaWModGFibGUoY3JvcF9tZW51JGNhbGxlcklkKSkpCm51bV9jcm9wX3R5cGVzJGZyZXF1ZW5jaWVzIDwtIG51bV9jcm9wX3R5cGVzJGFzLm51bWVyaWMudGFibGUuY3JvcF9tZW51LmNhbGxlcklkLgoKc3VtbWFyeShudW1fY3JvcF90eXBlcyRmcmVxdWVuY2llcykKCmdncGxvdChudW1fY3JvcF90eXBlcywgYWVzKGZyZXF1ZW5jaWVzKSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG9yPSJibGFjayIsIGZpbGw9InJlZCIpICsKICBsYWJzKAogICAgdGl0bGUgPSAnRGlzdHJpYnV0aW9uIG9mIG51bWJlciBjcm9wcyBldmVyIHNlbGVjdGVkIGJ5IGluZGl2aWR1YWwgXG4KICAgICAgTWluLiAgMXN0IFF1LiAgTWVkaWFuICAgIE1lYW4gICAzcmQgUXUuICAgIE1heC4gCiAgMS4wMDAgICAgIDIuMDAwICAgICA0LjAwMCAgICAgIDQuOTE1ICAgICA3LjAwMCAgICAgMTUuMDAwICcsCiAgICB4ID0gJ051bWJlciBvZiBjcm9wcyBzZWxlY3RlZCAnCiAgKQpgYGAKCgpgYGB7cn0KI0dFVFRJTkcgQk9USCBUSEUgQ1JPUCBNRU5VUyBmb3IgYm90aCByYWluIGFuZCBoaGkKcmFpbl9jcm9wX21lbnUgPC0gZmlsdGVyKGxvZ19kYXRhLCBncmVwbCgiQ1JPUCBNRU5VIC0gIixsb2dJbmZvKSkKcmFpbl9jcm9wX21lbnUgPC0gZmlsdGVyKHJhaW5fY3JvcF9tZW51LCAhZ3JlcGwoIkhISSIsbG9nSW5mbykpCgpyYWluX2Nyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9jcm9wX21lbnUkbG9nSW5mbywgIkNST1AgTUVOVSAtICIsICIiKQpyYWluX2Nyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9jcm9wX21lbnUkbG9nSW5mbywgIiBTRUxFQ1RFRCIsICIiKQpyYWluX2Nyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9jcm9wX21lbnUkbG9nSW5mbywgIiBQVElPTiIsICJPUFRJT04iKQp0YWJsZShyYWluX2Nyb3BfbWVudSRsb2dJbmZvKQoKCiNBRERJTkcgVEhFIE5VTUJFUlMKcmFpbl9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fY3JvcF9tZW51JGxvZ0luZm8sICJCQVJMRVkgT1BUSU9OIiwgIjEgLSBCQVJMRVkgT1BUSU9OIikKcmFpbl9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fY3JvcF9tZW51JGxvZ0luZm8sICJNQUlaRSBPUFRJT04iLCAiMiAtIE1BSVpFIE9QVElPTiIpCnJhaW5fY3JvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShyYWluX2Nyb3BfbWVudSRsb2dJbmZvLCAiU09SR0hVTSBPUFRJT04iLCAiMyAtIFNPUkdIVU0gT1BUSU9OIikKcmFpbl9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fY3JvcF9tZW51JGxvZ0luZm8sICJURUYgT1BUSU9OIiwgIjQgLSBURUYgT1BUSU9OIikKcmFpbl9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fY3JvcF9tZW51JGxvZ0luZm8sICJXSEVBVCBPUFRJT04iLCAiNSAtIFdIRUFUIE9QVElPTiIpCnJhaW5fY3JvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShyYWluX2Nyb3BfbWVudSRsb2dJbmZvLCAiU0VTQU1FIE9QVElPTiIsICI2IC0gU0VTQU1FIE9QVElPTiIpCnJhaW5fY3JvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShyYWluX2Nyb3BfbWVudSRsb2dJbmZvLCAiRkFWQSBCRUFOIE9QVElPTiIsICI3IC0gRkFWQSBCRUFOIE9QVElPTiIpCnJhaW5fY3JvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShyYWluX2Nyb3BfbWVudSRsb2dJbmZvLCAiQ0hJQ0tQRUEgT1BUSU9OIiwgIjggLSBDSElDS1BFQSBPUFRJT04iKQpyYWluX2Nyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9jcm9wX21lbnUkbG9nSW5mbywgIkNPTU1PTiBCRUFOT1BUSU9OIiwgIjkgLSBDT01NT04gQkVBTiBPUFRJT04iKQpyYWluX2Nyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9jcm9wX21lbnUkbG9nSW5mbywgIkNPVFRPTiBPUFRJT04iLCAiMTAgLSBDT1RUT04gT1BUSU9OIikKcmFpbl9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fY3JvcF9tZW51JGxvZ0luZm8sICJDUk9QIE1FTlUgUkVQTEFZRUQiLCAiIyAtIENST1AgTUVOVSBSRVBMQVlFRCIpCnJhaW5fY3JvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShyYWluX2Nyb3BfbWVudSRsb2dJbmZvLCAiR08gVE8gTUFJTiBNRU5VIE9QVElPTiIsICIqIC0gR08gVE8gTUFJTiBNRU5VIE9QVElPTiIpCgojZml4ZXMKcmFpbl9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKHJhaW5fY3JvcF9tZW51JGxvZ0luZm8sICJNQUxUIDEgLSAiLCAiTUFMVCAiKQpyYWluX2Nyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UocmFpbl9jcm9wX21lbnUkbG9nSW5mbywgIkRVUkVNIDUgLSAiLCAiRFVSRU0gIikKCgoKI3Bsb3R0aW5nIHJhaW4KZ2dwbG90KHJhaW5fY3JvcF9tZW51LCBhZXMoeD1mY3RfaW5mcmVxKGxvZ0luZm8pKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0ID0xLCBzaXplID0gNykpKwogIGdlb21fYmFyKGZpbGw9J2JsYWNrJykrCiAgZ2VvbV90ZXh0KHN0YXQ9J2NvdW50JywgYWVzKGxhYmVsPS4uY291bnQuLiksIHZqdXN0PS0xKSsKICB5bGltKDAsMzIwMCkrCiAgbGFicygKICAgIHRpdGxlID0gJ1JhaW4gQ3JvcCBtZW51IFRvdGFsIFNlbGVjdGlvbnMgd2l0aCBCdXR0b24gQ2hvaWNlcycsCiAgICB4ID0gJ0Nyb3BzJywKICAgIHk9ICdjb3VudCcKICApCgoKI2dldHRpbmcgdGhlIEhISSBNRU5VCmhoaV9jcm9wX21lbnUgPC0gZmlsdGVyKGxvZ19kYXRhLCBncmVwbCgiSEhJQ1JPUCBNRU5VIC0gIixsb2dJbmZvKSkKaGhpX2Nyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoaGhpX2Nyb3BfbWVudSRsb2dJbmZvLCAiSEhJQ1JPUCBNRU5VIC0gIiwgIiIpCmhoaV9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGhoaV9jcm9wX21lbnUkbG9nSW5mbywgIiBTRUxFQ1RFRCIsICIiKQp0YWJsZShoaGlfY3JvcF9tZW51JGxvZ0luZm8pCgojQURESU5HIFRIRSBOVU1CRVJTCmhoaV9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGhoaV9jcm9wX21lbnUkbG9nSW5mbywgIlBPVEFUTyBPUFRJT04iLCAiMSAtIFBPVEFUTyBPUFRJT04iKQpoaGlfY3JvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShoaGlfY3JvcF9tZW51JGxvZ0luZm8sICJDQVJST1QgT1BUSU9OIiwgIjIgLSBDQVJST1QgT1BUSU9OIikKaGhpX2Nyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoaGhpX2Nyb3BfbWVudSRsb2dJbmZvLCAiT05JT04gT1BUSU9OIiwgIjMgLSBPTklPTiBPUFRJT04iKQpoaGlfY3JvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShoaGlfY3JvcF9tZW51JGxvZ0luZm8sICJHQVJMSUMgT1BUSU9OIiwgIjQgLSBHQVJMSUMgT1BUSU9OIikKaGhpX2Nyb3BfbWVudSRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoaGhpX2Nyb3BfbWVudSRsb2dJbmZvLCAiVE9NQVRPIE9QVElPTiIsICI1IC0gVE9NQVRPIE9QVElPTiIpCmhoaV9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGhoaV9jcm9wX21lbnUkbG9nSW5mbywgIlBBUEVSIE9QVElPTiIsICI2IC0gUEVQUEVSIE9QVElPTiIpCmhoaV9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGhoaV9jcm9wX21lbnUkbG9nSW5mbywgIkhFQUQgQ0FCQkFHRSBPUFRJT04iLCAiNyAtIEhFQUQgQ0FCQkFHRSBPUFRJT04iKQpoaGlfY3JvcF9tZW51JGxvZ0luZm88LSBzdHJfcmVwbGFjZShoaGlfY3JvcF9tZW51JGxvZ0luZm8sICJDUk9QIE1FTlUgUkVQTEFZRUQiLCAiIyAtIENST1AgTUVOVSBSRVBMQVlFRCIpCmhoaV9jcm9wX21lbnUkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGhoaV9jcm9wX21lbnUkbG9nSW5mbywgIkdPIFRPIE1BSU4gTUVOVSBPUFRJT04iLCAiKiAtIEdPIFRPIE1BSU4gTUVOVSBPUFRJT04iKQoKI3Bsb3R0aW5nIEhISQpnZ3Bsb3QoaGhpX2Nyb3BfbWVudSwgYWVzKHg9ZmN0X2luZnJlcShsb2dJbmZvKSkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9MSwgc2l6ZSA9IDcpKSsKICBnZW9tX2JhcihmaWxsPSdicm93bicpKwogIGdlb21fdGV4dChzdGF0PSdjb3VudCcsIGFlcyhsYWJlbD0uLmNvdW50Li4pLCB2anVzdD0tMSkrCiAgeWxpbSgwLDE3NTApKwogIGxhYnMoCiAgICB0aXRsZSA9ICdISEkgQ3JvcCBNZW51IFRvdGFsIFNlbGVjdGlvbnMgd2l0aCBCdXR0b24gQ2hvaWNlcycsCiAgICB4ID0gJ0Nyb3BzJywKICAgIHk9ICdjb3VudCcKICApCgpgYGAKCgpgYGB7cn0KCiMgVE9UQUwgQ1JPUFMgQlkgQ09ORU5UIFBMQVlFREUgRVZFUiEhISEKY29udGVudF9jcm9wX3BsYXllZCA8LSBmaWx0ZXIobG9nX2RhdGEsIGdyZXBsKCJDT05URU5UIFBMQVlFRCAtICIsbG9nSW5mbykpCmNvbnRlbnRfY3JvcF9wbGF5ZWQgPC0gZmlsdGVyKGNvbnRlbnRfY3JvcF9wbGF5ZWQsICFncmVwbCgiTElWRVNUT0NLIixsb2dJbmZvKSkKY29udGVudF9jcm9wX3BsYXllZCA8LSBmaWx0ZXIoY29udGVudF9jcm9wX3BsYXllZCwgIWdyZXBsKCJBUElDVUxUVVJFIixsb2dJbmZvKSkKY29udGVudF9jcm9wX3BsYXllZCA8LSBmaWx0ZXIoY29udGVudF9jcm9wX3BsYXllZCwgIWdyZXBsKCJDT1ZJRCIsbG9nSW5mbykpCmNvbnRlbnRfY3JvcF9wbGF5ZWQgPC0gZmlsdGVyKGNvbnRlbnRfY3JvcF9wbGF5ZWQsICFncmVwbCgiREFJUlkiLGxvZ0luZm8pKQpjb250ZW50X2Nyb3BfcGxheWVkIDwtIGZpbHRlcihjb250ZW50X2Nyb3BfcGxheWVkLCAhZ3JlcGwoIkZBTUlMWSIsbG9nSW5mbykpCmNvbnRlbnRfY3JvcF9wbGF5ZWQgPC0gZmlsdGVyKGNvbnRlbnRfY3JvcF9wbGF5ZWQsICFncmVwbCgiQ0FUVExFIixsb2dJbmZvKSkKY29udGVudF9jcm9wX3BsYXllZCA8LSBmaWx0ZXIoY29udGVudF9jcm9wX3BsYXllZCwgIWdyZXBsKCJGQVRURU5JTkciLGxvZ0luZm8pKQpjb250ZW50X2Nyb3BfcGxheWVkIDwtIGZpbHRlcihjb250ZW50X2Nyb3BfcGxheWVkLCAhZ3JlcGwoIlBPVUxUUlkiLGxvZ0luZm8pKQpjb250ZW50X2Nyb3BfcGxheWVkIDwtIGZpbHRlcihjb250ZW50X2Nyb3BfcGxheWVkLCAhZ3JlcGwoIlNBRkUiLGxvZ0luZm8pKQpjb250ZW50X2Nyb3BfcGxheWVkIDwtIGZpbHRlcihjb250ZW50X2Nyb3BfcGxheWVkLCAhZ3JlcGwoIk1JU0NPTkNFUFRJT05TIixsb2dJbmZvKSkKCiNnZXR0aW5nIHJpZCBvZiB0aGUgbGFuZ3VhZ2VzL2NvbnRlbnQKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiLSBBTUhBUklDIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIi0gT1JPTUlGRkEiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiLSBUSUdSSUdOQSIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICItIFdPTEFZSVRUQSIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICItIFdPTEFZVElHTkEiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiLSBTSURBTUlHTkEiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiQ09OVEVOVCBQTEFZRUQgLSAiLCAiIikKCiNnZXR0aW5nIHJpZCBvZiBtZW51IGxhYmVscwpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJBUFBMWUlORyBGRVJUSUxJWkVSIC0gIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIkRJU0VBU0UgQ09OVFJPTCAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJGRVJUSUxJWkVSIEFQUExJQ0FUSU9OIFJBVEUgLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiRkVSVElMSVpFUiBTSURFIERSRVNTSU5HIC0gIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIkhBUlJPV0lORyBBTkQgRUFSVEhOSU5HIFVQIC0gIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIkhBUlZFU1RJTkcgLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiSEFSVkVTVElORyBURUNITklRVUUgLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiSE9XIFRPIEFERCBXQVRFUiAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJIT1cgVE8gUExBTlQgLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiSE9XIFRPIFNFTEVDVCBBTkQgQlVZIFNFRURTIC0gIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIklOU0VDVCBDT05UUk9MIC0gIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIkxBTkQgUFJFUEFSQVRJT04gLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiTUFOQUdJTkcgV0VFRFMgLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiTU9JU1RVUkUgQ09OU0VSVkFUSU9OIC0gIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIk9QVElNVU0gU1BBQ0lORyBCRVRXRUVOIFJPV1MgQU5EIFBMQU5UUyAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJQTE9UIFBSRVBBUkFUSU9OIC0gIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIlBSRS1JUlJJR0FUSU9OIC0gIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIlBST0NFU1NJTkcgLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiXFwoIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIlxcKSIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJQUk9DRVNTSU5HIEhISSAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJQUk9URUNUSU9OIE9OIElOU0VDVFMgQU5EIERJU0VBU0VTIC0gIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIlNFRUQgUkFURSAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJTRUVEIFZBUklUWSAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJTRUVEIFZBUklUWSAtIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIlNPSUwgREVQVEggLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiU09JTCBERVBUSCAtIiwgIiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIlRIUkVTSElORyBBTkQgQ0xFQU5JTkcgLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiVFJBTlNQTEFOVElORyAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXRUVEIENPTlRST0wgLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiV0hFTiBBTkQgSE9XIE1VQ0ggV0FURVIgVE8gQUREIC0gREVHQSAtIENMQVkgLSAiLCAiIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiSEVOIEFORCBIT1cgTVVDSCBXQVRFUiBUTyBBREQgLSBERUdBIC0gTE9BTSAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXSEVOIEFORCBIT1cgTVVDSCBXQVRFUiBUTyBBREQgLSBLT0xBIC0gQ0xBWSAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXSEVOIEFORCBIT1cgTVVDSCBXQVRFUiBUTyBBREQgLSBLT0xBIC0gU0FORCAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXSEVOIEFORCBIT1cgTVVDSCBXQVRFUiBUTyBBREQgLSBERUdBIC0gU0FORCAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXSEVOIEFORCBIT1cgTVVDSCBXQVRFUiBUTyBBREQgLSBLT0xBIC0gTE9BTSAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXSEVOIEFORCBIT1cgTVVDSCBXQVRFUiBUTyBBREQgLSBXT1lFTkFERUdBIC0gQ0xBWSAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXSEVOIEFORCBIT1cgTVVDSCBXQVRFUiBUTyBBREQgLSBXT1lFTkFERUdBIC0gTE9BTSAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXSEVOIEFORCBIT1cgTVVDSCBXQVRFUiBUTyBBREQgLSBXT1lFTkFERUdBIC0gU0FORCAtICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXSEVOIFRPIEhBUlZFU1QgLSAiLCAiIikKCiNmaXhpbmcgZXh0cmEgY2hhbmdlcwpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZV9hbGwoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiICIsICIiKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZV9hbGwoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiV0MiLCAiQyIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlX2FsbChjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXRyIsICJHIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2VfYWxsKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIldPIiwgIk8iKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZV9hbGwoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiV1AiLCAiUCIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlX2FsbChjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJXVCIsICJUIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2VfYWxsKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIldIRUFEQ0FCQkFHRSIsICJIRUFEQ0FCQkFHRSIpCgojQURESU5HIFRIRSBOVU1CRVJTCiNBRERJTkcgVEhFIE5VTUJFUlMKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiUE9UQVRPIiwgIjEgLSBQT1RBVE8iKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJDQVJST1QiLCAiMiAtIENBUlJPVCIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIk9OSU9OIiwgIjMgLSBPTklPTiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIkdBUkxJQyIsICI0IC0gR0FSTElDIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiVE9NQVRPIiwgIjUgLSBUT01BVE8iKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJQRVBQRVIiLCAiNiAtIFBFUFBFUiBPUFRJT04iKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJIRUFEQ0FCQkFHRSIsICI3IC0gSEVBRCBDQUJCQUdFIikKCgpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJCQVJMRVkiLCAiMSAtIEJBUkxFWSIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIk1BSVpFIiwgIjIgLSBNQUlaRSIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIlNPUkdIVU0iLCAiMyAtIFNPUkdIVU0iKQpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJURUYiLCAiNCAtIFRFRiIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIldIRUFUIiwgIjUgLSBXSEVBVCIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIlNFU0FNRSIsICI2IC0gU0VTQU1FIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiRkFWQSBCRUFOUyIsICI3IC0gRkFWQSBCRUFOIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiQ0hJQ0tQRUEiLCAiOCAtIENISUNLUEVBIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiQ09NTU9OQkVBTlMiLCAiOSAtIENPTU1PTiBCRUFOUyIpCmNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNvbnRlbnRfY3JvcF9wbGF5ZWQkbG9nSW5mbywgIkNPVFRPTiIsICIxMCAtIENPVFRPTiIpCgpjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjb250ZW50X2Nyb3BfcGxheWVkJGxvZ0luZm8sICJEVVJBTUU1IC0gV0hFQVQiLCAiRFVSQU1FIFdIRUFUIikKY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY29udGVudF9jcm9wX3BsYXllZCRsb2dJbmZvLCAiTUFMVDEgLSBCQVJMRVkiLCAiTUFMVCBCQVJMRVkiKQoKCgo/Z2VvbV90ZXh0CmdncGxvdChjb250ZW50X2Nyb3BfcGxheWVkLCBhZXMoeD1mY3RfaW5mcmVxKGxvZ0luZm8pKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0ID0xLCBzaXplID0gNykpKwogIGdlb21fYmFyKGZpbGw9J3NreSBibHVlJykrCiAgZ2VvbV90ZXh0KHN0YXQ9J2NvdW50JywgYWVzKGxhYmVsPS4uY291bnQuLiksIHZqdXN0PS0xLHNpemU9MykrCiAgeWxpbSgwLDI3NTApKwogIGxhYnMoCiAgICB0aXRsZSA9ICdBTEwgQ3JvcHMgRXZlciBBY2Nlc3NlZCBBY3Jvc3MgQWxsIENhbGxzIHdpdGggTGFiZWxlZCBCdXR0b25zJywKICAgIHggPSAnQ3JvcHMnLAogICAgeT0gJ2NvdW50JwogICkKYGBgCgoKCgoKI1doYXQgYWJvdXQgYSBuaWNlIGNyb3AgYnJlYWtkb3duIHBlciBtb250aD8KYGBge3J9Cgpjcm9wX21vbnRoIDwtIGxvZ19kYXRhICU+JQogIGZpbHRlcihncmVwbCgiQ1JPUCBNRU5VIC0gIixsb2dJbmZvKSkgJT4lCiAgZmlsdGVyKCFncmVwbCgiSEhJIixsb2dJbmZvKSkgJT4lCiAgZmlsdGVyKCFncmVwbCgiUkVQTEFZRUQiLGxvZ0luZm8pKQoKY3JvcF9tb250aCA8LSBjcm9wX21vbnRoICU+JQogIGdyb3VwX2J5KGNhbGxlcklkLCBsb2dJbmZvLG1vbnRoKSAlPiUKICBjb3VudCgpCgpjcm9wX21vbnRoJGxvZ0luZm88LSBzdHJfcmVwbGFjZShjcm9wX21vbnRoJGxvZ0luZm8sICJDUk9QIE1FTlUgLSAiLCAiIikKY3JvcF9tb250aCRsb2dJbmZvPC0gc3RyX3JlcGxhY2UoY3JvcF9tb250aCRsb2dJbmZvLCAiIFNFTEVDVEVEIiwgIiIpCmNyb3BfbW9udGgkbG9nSW5mbzwtIHN0cl9yZXBsYWNlKGNyb3BfbW9udGgkbG9nSW5mbywgIkdPIFRPIiwgIiIpCgoKY3JvcF90cmFjayA8LSBjcm9wX21vbnRoICU+JQogIGZpbHRlcihtb250aCA9PSAxKQpnZ3Bsb3QoY3JvcF90cmFjaywgYWVzKHg9bG9nSW5mbykpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9MSwgc2l6ZSA9IDcpKSsKICBnZW9tX2JhcigpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdDcm9wIG1lbnUgYnJlYWtkb3duIEphbicsCiAgICB4ID0gJ0Nyb3BzJywKICAgIHk9ICdjb3VudCcKICApCiAgCmNyb3BfdHJhY2sgPC0gY3JvcF9tb250aCAlPiUKICBmaWx0ZXIobW9udGggPT0gMikKZ2dwbG90KGNyb3BfdHJhY2ssIGFlcyh4PWxvZ0luZm8pKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3QgPTEsIHNpemUgPSA3KSkrCiAgZ2VvbV9iYXIoKSsKICBsYWJzKAogICAgdGl0bGUgPSAnQ3JvcCBtZW51IGJyZWFrZG93biBmZWInLAogICAgeCA9ICdDcm9wcycsCiAgICB5PSAnY291bnQnCiAgKQpjcm9wX3RyYWNrIDwtIGNyb3BfbW9udGggJT4lCiAgZmlsdGVyKG1vbnRoID09IDMpCmdncGxvdChjcm9wX3RyYWNrLCBhZXMoeD1sb2dJbmZvKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0ID0xLCBzaXplID0gNykpKwogIGdlb21fYmFyKCkrCiAgbGFicygKICAgIHRpdGxlID0gJ0Nyb3AgbWVudSBicmVha2Rvd24gbWFyJywKICAgIHggPSAnQ3JvcHMnLAogICAgeT0gJ2NvdW50JwogICkKY3JvcF90cmFjayA8LSBjcm9wX21vbnRoICU+JQogIGZpbHRlcihtb250aCA9PSA0KQpnZ3Bsb3QoY3JvcF90cmFjaywgYWVzKHg9bG9nSW5mbykpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9MSwgc2l6ZSA9IDcpKSsKICBnZW9tX2JhcigpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdDcm9wIG1lbnUgYnJlYWtkb3duIGFwcmlsJywKICAgIHggPSAnQ3JvcHMnLAogICAgeT0gJ2NvdW50JwogICkKY3JvcF90cmFjayA8LSBjcm9wX21vbnRoICU+JQogIGZpbHRlcihtb250aCA9PSA1KQpnZ3Bsb3QoY3JvcF90cmFjaywgYWVzKHg9bG9nSW5mbykpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9MSwgc2l6ZSA9IDcpKSsKICBnZW9tX2JhcigpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdDcm9wIG1lbnUgYnJlYWtkb3duIG1heScsCiAgICB4ID0gJ0Nyb3BzJywKICAgIHk9ICdjb3VudCcKICApCmNyb3BfdHJhY2sgPC0gY3JvcF9tb250aCAlPiUKICBmaWx0ZXIobW9udGggPT0gNikKZ2dwbG90KGNyb3BfdHJhY2ssIGFlcyh4PWxvZ0luZm8pKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3QgPTEsIHNpemUgPSA3KSkrCiAgZ2VvbV9iYXIoKSsKICBsYWJzKAogICAgdGl0bGUgPSAnQ3JvcCBtZW51IGJyZWFrZG93biBqdW5lJywKICAgIHggPSAnQ3JvcHMnLAogICAgeT0gJ2NvdW50JwogICkKY3JvcF90cmFjayA8LSBjcm9wX21vbnRoICU+JQogIGZpbHRlcihtb250aCA9PSA3KQpnZ3Bsb3QoY3JvcF90cmFjaywgYWVzKHg9bG9nSW5mbykpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9MSwgc2l6ZSA9IDcpKSsKICBnZW9tX2JhcigpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdDcm9wIG1lbnUgYnJlYWtkb3duIGp1bHknLAogICAgeCA9ICdDcm9wcycsCiAgICB5PSAnY291bnQnCiAgKQpjcm9wX3RyYWNrIDwtIGNyb3BfbW9udGggJT4lCiAgZmlsdGVyKG1vbnRoID09IDgpCmdncGxvdChjcm9wX3RyYWNrLCBhZXMoeD1sb2dJbmZvKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0ID0xLCBzaXplID0gNykpKwogIGdlb21fYmFyKCkrCiAgbGFicygKICAgIHRpdGxlID0gJ0Nyb3AgbWVudSBicmVha2Rvd24gYXVnJywKICAgIHggPSAnQ3JvcHMnLAogICAgeT0gJ2NvdW50JwogICkKY3JvcF90cmFjayA8LSBjcm9wX21vbnRoICU+JQogIGZpbHRlcihtb250aCA9PSA5KQpnZ3Bsb3QoY3JvcF90cmFjaywgYWVzKHg9bG9nSW5mbykpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9MSwgc2l6ZSA9IDcpKSsKICBnZW9tX2JhcigpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdDcm9wIG1lbnUgYnJlYWtkb3duIHNlcCcsCiAgICB4ID0gJ0Nyb3BzJywKICAgIHk9ICdjb3VudCcKICApCmNyb3BfdHJhY2sgPC0gY3JvcF9tb250aCAlPiUKICBmaWx0ZXIobW9udGggPT0gMTApCmdncGxvdChjcm9wX3RyYWNrLCBhZXMoeD1sb2dJbmZvKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0ID0xLCBzaXplID0gNykpKwogIGdlb21fYmFyKCkrCiAgbGFicygKICAgIHRpdGxlID0gJ0Nyb3AgbWVudSBicmVha2Rvd24gb2N0JywKICAgIHggPSAnQ3JvcHMnLAogICAgeT0gJ2NvdW50JwogICkKY3JvcF90cmFjayA8LSBjcm9wX21vbnRoICU+JQogIGZpbHRlcihtb250aCA9PSAxMSkKZ2dwbG90KGNyb3BfdHJhY2ssIGFlcyh4PWxvZ0luZm8pKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3QgPTEsIHNpemUgPSA3KSkrCiAgZ2VvbV9iYXIoKSsKICBsYWJzKAogICAgdGl0bGUgPSAnQ3JvcCBtZW51IGJyZWFrZG93biBub3YnLAogICAgeCA9ICdDcm9wcycsCiAgICB5PSAnY291bnQnCiAgKQpjcm9wX3RyYWNrIDwtIGNyb3BfbW9udGggJT4lCiAgZmlsdGVyKG1vbnRoID09IDEyKQpnZ3Bsb3QoY3JvcF90cmFjaywgYWVzKHg9bG9nSW5mbykpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9MSwgc2l6ZSA9IDcpKSsKICBnZW9tX2JhcigpKwogIGxhYnMoCiAgICB0aXRsZSA9ICdDcm9wIG1lbnUgYnJlYWtkb3duIGRlYycsCiAgICB4ID0gJ0Nyb3BzJywKICAgIHk9ICdjb3VudCcKICApCgoKYGBgCgo=